1 /***********************************************************************
2 *
3 * GEOS - Geometry Engine Open Source
4 * http://trac.osgeo.org/geos
5 *
6 * Copyright (C) 2010 Sandro Santilli <strk@kbt.io>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301 USA
22 *
23 ***********************************************************************/
24
25 /* PHP stuff */
26 #include "php.h"
27 #include "ext/standard/info.h" /* for php_info_... */
28 #include "Zend/zend_exceptions.h" /* for zend_throw_exception_object */
29
30 /* GEOS stuff */
31 #include "geos_c.h"
32
33 /* Own stuff */
34 #include "php_geos.h"
35
36 #if PHP_MAJOR_VERSION >= 8
37 #define TSRMLS_C
38 #define TSRMLS_CC
39 #define TSRMLS_DC
40 #define TSRMLS_FETCH()
41 #endif
42
43 static ZEND_DECLARE_MODULE_GLOBALS(geos);
44 static PHP_GINIT_FUNCTION(geos);
45
46 PHP_MINIT_FUNCTION(geos);
47 PHP_MSHUTDOWN_FUNCTION(geos);
48 PHP_RINIT_FUNCTION(geos);
49 PHP_RSHUTDOWN_FUNCTION(geos);
50 PHP_MINFO_FUNCTION(geos);
51 PHP_FUNCTION(GEOSVersion);
52 PHP_FUNCTION(GEOSPolygonize);
53 PHP_FUNCTION(GEOSLineMerge);
54
55 #ifdef HAVE_GEOS_SHARED_PATHS
56 PHP_FUNCTION(GEOSSharedPaths);
57 #endif
58
59 #ifdef HAVE_GEOS_RELATE_PATTERN_MATCH
60 PHP_FUNCTION(GEOSRelateMatch);
61 #endif
62
63 #if PHP_VERSION_ID < 50399
64 #define zend_function_entry function_entry
65 #endif
66
67 #if PHP_VERSION_ID >= 70000
68 # define GEOS_PHP_DTOR_OBJECT zend_object
69 # define zend_object_value zend_object *
70 # define zend_uint size_t
71 # define MAKE_STD_ZVAL(x) x = emalloc(sizeof(zval))
72 # define GEOS_PHP_RETURN_STRING(x) { RETVAL_STRING((x)); efree((x)); return; }
73 # define GEOS_PHP_RETURN_STRINGL(x,s) { RETVAL_STRINGL((x),(s)); efree((x)); return; }
74 # define GEOS_PHP_ADD_ASSOC_ARRAY(a,k,v) { add_assoc_string((a), (k), (v)); efree((v)); }
75 # define GEOS_PHP_ADD_ASSOC_ZVAL(a,k,v) { add_assoc_zval((a), (k), (v)); efree((v)); }
76 # define GEOS_PHP_HASH_GET_CUR_KEY(s,k,i) zend_hash_get_current_key((s), (k), (i))
77 # define GEOS_PHP_HASH_GET_CUR_DATA(h,d) ( d = zend_hash_get_current_data((h)) )
78 # define GEOS_PHP_ZVAL zval *
79 #else /* PHP_VERSION_ID < 70000 */
80 # define GEOS_PHP_DTOR_OBJECT void
81 # define GEOS_PHP_RETURN_STRING(x) RETURN_STRING((x),0)
82 # define GEOS_PHP_RETURN_STRINGL(x,s) RETURN_STRINGL((x),(s),0)
83 # define GEOS_PHP_ADD_ASSOC_ARRAY(a,k,v) add_assoc_string((a), (k), (v), 0)
84 # define GEOS_PHP_ADD_ASSOC_ZVAL(a,k,v) add_assoc_zval((a), (k), (v))
85 # define GEOS_PHP_HASH_GET_CUR_KEY(s,k,i) zend_hash_get_current_key((s), (k), (i), 0)
86 # define zend_string char
87 # define ZSTR_VAL(x) (x)
88 # define GEOS_PHP_HASH_GET_CUR_DATA(h,d) zend_hash_get_current_data((h),(void**)&(d))
89 # define GEOS_PHP_ZVAL zval **
90 #endif
91
92
93 static zend_function_entry geos_functions[] = {
94 PHP_FE(GEOSVersion, NULL)
95 PHP_FE(GEOSPolygonize, NULL)
96 PHP_FE(GEOSLineMerge, NULL)
97
98 # ifdef HAVE_GEOS_SHARED_PATHS
99 PHP_FE(GEOSSharedPaths, NULL)
100 # endif
101
102 # ifdef HAVE_GEOS_RELATE_PATTERN_MATCH
103 PHP_FE(GEOSRelateMatch, NULL)
104 # endif
105 {NULL, NULL, NULL}
106 };
107
108 zend_module_entry geos_module_entry = {
109 STANDARD_MODULE_HEADER,
110 PHP_GEOS_EXTNAME,
111 geos_functions,
112 PHP_MINIT(geos), /* module init function */
113 PHP_MSHUTDOWN(geos), /* module shutdown function */
114 PHP_RINIT(geos), /* request init function */
115 PHP_RSHUTDOWN(geos), /* request shutdown function */
116 PHP_MINFO(geos), /* module info function */
117 PHP_GEOS_VERSION,
118 PHP_MODULE_GLOBALS(geos), /* globals descriptor */
119 PHP_GINIT(geos), /* globals ctor */
120 NULL, /* globals dtor */
121 NULL, /* post deactivate */
122 STANDARD_MODULE_PROPERTIES_EX
123 };
124
125 #ifdef COMPILE_DL_GEOS
ZEND_GET_MODULE(geos)126 ZEND_GET_MODULE(geos)
127 #endif
128
129 /* -- Utility functions ---------------------- */
130
131 static void noticeHandler(const char *fmt, ...)
132 {
133 TSRMLS_FETCH();
134 char message[256];
135 va_list args;
136 va_start(args, fmt);
137 vsnprintf(message, sizeof(message) - 1, fmt, args);
138 va_end(args);
139
140 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", message);
141 }
142
errorHandler(const char * fmt,...)143 static void errorHandler(const char *fmt, ...)
144 {
145 TSRMLS_FETCH();
146 char message[256];
147 va_list args;
148 va_start(args, fmt);
149 vsnprintf(message, sizeof(message) - 1, fmt, args);
150 va_end(args);
151
152 /* TODO: use a GEOSException ? */
153 zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C),
154 1 TSRMLS_CC, "%s", message);
155
156 }
157
158 typedef struct Proxy_t {
159 #if PHP_VERSION_ID >= 70000
160 int id;
161 void* relay;
162 zend_object std;
163 #else
164 zend_object std;
165 void* relay;
166 #endif
167 } Proxy;
168
169 #if PHP_VERSION_ID >= 70000
php_geos_fetch_object(zend_object * obj)170 static inline Proxy *php_geos_fetch_object(zend_object *obj) {
171 return (Proxy *)((char *) obj - XtOffsetOf(Proxy, std));
172 }
173 # define Z_GEOS_OBJ_P(zv) (Proxy *)((char *) (Z_OBJ_P(zv)) - XtOffsetOf(Proxy, std))
174 #else
175 # ifdef Z_OBJ
176 # define Z_GEOS_OBJ_P(zv) (Proxy*)Z_OBJ(*val TSRMLS_CC)
177 # else
178 # define Z_GEOS_OBJ_P(zv) (Proxy*)zend_object_store_get_object(val TSRMLS_CC)
179 # endif
180 #endif
181
182 static void
setRelay(zval * val,void * obj)183 setRelay(zval* val, void* obj) {
184 TSRMLS_FETCH();
185
186 Proxy* proxy = Z_GEOS_OBJ_P(val);
187
188 proxy->relay = obj;
189 }
190
191 static inline void *
getRelay(zval * val,zend_class_entry * ce)192 getRelay(zval* val, zend_class_entry* ce) {
193 TSRMLS_FETCH();
194
195 Proxy* proxy = Z_GEOS_OBJ_P(val);
196
197 if ( proxy->std.ce != ce ) {
198 php_error_docref(NULL TSRMLS_CC, E_ERROR,
199 "Relay object is not an %s", ce->name);
200 }
201 if ( ! proxy->relay ) {
202 php_error_docref(NULL TSRMLS_CC, E_ERROR,
203 "Relay object for object of type %s is not set", ce->name);
204 }
205 return proxy->relay;
206 }
207
getZvalAsLong(GEOS_PHP_ZVAL val)208 static long getZvalAsLong(GEOS_PHP_ZVAL val)
209 {
210 long ret;
211 zval tmp;
212
213 #if PHP_VERSION_ID >= 70000
214 tmp = *val;
215 #else
216 tmp = **val;
217 #endif
218 zval_copy_ctor(&tmp);
219 convert_to_long(&tmp);
220 ret = Z_LVAL(tmp);
221 zval_dtor(&tmp);
222 return ret;
223 }
224
getZvalAsDouble(GEOS_PHP_ZVAL val)225 static long getZvalAsDouble(GEOS_PHP_ZVAL val)
226 {
227 double ret;
228 zval tmp;
229
230 #if PHP_VERSION_ID >= 70000
231 tmp = *val;
232 #else
233 tmp = **val;
234 #endif
235 zval_copy_ctor(&tmp);
236 convert_to_double(&tmp);
237 ret = Z_DVAL(tmp);
238 zval_dtor(&tmp);
239 return ret;
240 }
241
242 static zend_object_value
Gen_create_obj(zend_class_entry * type,void (* dtor)(GEOS_PHP_DTOR_OBJECT * object TSRMLS_DC),zend_object_handlers * handlers)243 Gen_create_obj (zend_class_entry *type,
244 void (*dtor)(GEOS_PHP_DTOR_OBJECT *object TSRMLS_DC),
245 zend_object_handlers* handlers)
246 {
247 TSRMLS_FETCH();
248
249 #if PHP_VERSION_ID >= 70000
250
251 Proxy *obj = (Proxy *) ecalloc(1, sizeof(Proxy) + zend_object_properties_size(type));
252
253 zend_object_std_init(&obj->std, type TSRMLS_CC);
254 object_properties_init(&obj->std, type);
255
256 obj->std.handlers = handlers;
257
258 /* TODO: install the destructor ? (dtor) ! */
259 /* TODO: do not allocate a full Proxy if we're going to use an object */
260
261 return &obj->std;
262
263 #else /* PHP_VERSION_ID < 70000 */
264
265 zend_object_value retval;
266
267 Proxy *obj = (Proxy *)ecalloc(1, sizeof(Proxy));
268
269 obj->std.ce = type;
270
271 ALLOC_HASHTABLE(obj->std.properties);
272 zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
273 #if PHP_VERSION_ID < 50399
274 zend_hash_copy(obj->std.properties, &type->default_properties,
275 (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval *));
276 #else
277 object_properties_init(&(obj->std), type);
278 #endif
279
280 retval.handle = zend_objects_store_put(obj, NULL, dtor, NULL TSRMLS_CC);
281 retval.handlers = handlers;
282
283 return retval;
284
285 #endif /* PHP_VERSION_ID < 70000 */
286 }
287
288
289 /* -- class GEOSGeometry -------------------- */
290
291 PHP_METHOD(Geometry, __construct);
292 PHP_METHOD(Geometry, __toString);
293 PHP_METHOD(Geometry, project);
294 PHP_METHOD(Geometry, interpolate);
295 PHP_METHOD(Geometry, buffer);
296
297 #ifdef HAVE_GEOS_OFFSET_CURVE
298 PHP_METHOD(Geometry, offsetCurve);
299 #endif
300
301 PHP_METHOD(Geometry, envelope);
302 PHP_METHOD(Geometry, intersection);
303 PHP_METHOD(Geometry, convexHull);
304 PHP_METHOD(Geometry, difference);
305 PHP_METHOD(Geometry, symDifference);
306 PHP_METHOD(Geometry, boundary);
307 PHP_METHOD(Geometry, union); /* also does union cascaded */
308 PHP_METHOD(Geometry, pointOnSurface);
309 PHP_METHOD(Geometry, centroid);
310 PHP_METHOD(Geometry, relate);
311
312 #ifdef HAVE_GEOS_RELATE_BOUNDARY_NODE_RULE
313 PHP_METHOD(Geometry, relateBoundaryNodeRule);
314 #endif
315
316 PHP_METHOD(Geometry, simplify); /* also does topology-preserving */
317 PHP_METHOD(Geometry, normalize);
318
319 #ifdef HAVE_GEOS_GEOM_SET_PRECISION
320 PHP_METHOD(Geometry, setPrecision);
321 #endif
322
323 #ifdef HAVE_GEOS_GEOM_GET_PRECISION
324 PHP_METHOD(Geometry, getPrecision);
325 #endif
326
327 #ifdef HAVE_GEOS_GEOM_EXTRACT_UNIQUE_POINTS
328 PHP_METHOD(Geometry, extractUniquePoints);
329 #endif
330
331 PHP_METHOD(Geometry, disjoint);
332 PHP_METHOD(Geometry, touches);
333 PHP_METHOD(Geometry, intersects);
334 PHP_METHOD(Geometry, crosses);
335 PHP_METHOD(Geometry, within);
336 PHP_METHOD(Geometry, contains);
337 PHP_METHOD(Geometry, overlaps);
338
339 #ifdef HAVE_GEOS_COVERS
340 PHP_METHOD(Geometry, covers);
341 #endif
342
343 #ifdef HAVE_GEOS_COVERED_BY
344 PHP_METHOD(Geometry, coveredBy);
345 #endif
346
347 PHP_METHOD(Geometry, equals);
348 PHP_METHOD(Geometry, equalsExact);
349 PHP_METHOD(Geometry, isEmpty);
350
351 #ifdef HAVE_GEOS_IS_VALID_DETAIL
352 PHP_METHOD(Geometry, checkValidity);
353 #endif
354
355 PHP_METHOD(Geometry, isSimple);
356 PHP_METHOD(Geometry, isRing);
357 PHP_METHOD(Geometry, hasZ);
358
359 #ifdef HAVE_GEOS_IS_CLOSED
360 PHP_METHOD(Geometry, isClosed);
361 #endif
362
363 PHP_METHOD(Geometry, typeName);
364 PHP_METHOD(Geometry, typeId);
365 PHP_METHOD(Geometry, getSRID);
366 PHP_METHOD(Geometry, setSRID);
367 PHP_METHOD(Geometry, numGeometries);
368 PHP_METHOD(Geometry, geometryN);
369 PHP_METHOD(Geometry, numInteriorRings);
370
371 #ifdef HAVE_GEOS_GEOM_GET_NUM_POINTS
372 PHP_METHOD(Geometry, numPoints);
373 #endif
374
375 #ifdef HAVE_GEOS_GEOM_GET_X
376 PHP_METHOD(Geometry, getX);
377 #endif
378
379 #ifdef HAVE_GEOS_GEOM_GET_Y
380 PHP_METHOD(Geometry, getY);
381 #endif
382
383 PHP_METHOD(Geometry, interiorRingN);
384 PHP_METHOD(Geometry, exteriorRing);
385 PHP_METHOD(Geometry, numCoordinates);
386 PHP_METHOD(Geometry, dimension);
387
388 #ifdef HAVE_GEOS_GEOM_GET_COORDINATE_DIMENSION
389 PHP_METHOD(Geometry, coordinateDimension);
390 #endif
391
392 #ifdef HAVE_GEOS_GEOM_GET_POINT_N
393 PHP_METHOD(Geometry, pointN);
394 #endif
395
396 #ifdef HAVE_GEOS_GEOM_GET_START_POINT
397 PHP_METHOD(Geometry, startPoint);
398 #endif
399
400 #ifdef HAVE_GEOS_GEOM_GET_END_POINT
401 PHP_METHOD(Geometry, endPoint);
402 #endif
403
404 PHP_METHOD(Geometry, area);
405 PHP_METHOD(Geometry, length);
406 PHP_METHOD(Geometry, distance);
407 PHP_METHOD(Geometry, hausdorffDistance);
408
409 #ifdef HAVE_GEOS_SNAP
410 PHP_METHOD(Geometry, snapTo);
411 #endif
412
413 #ifdef HAVE_GEOS_NODE
414 PHP_METHOD(Geometry, node);
415 #endif
416
417 #ifdef HAVE_GEOS_DELAUNAY_TRIANGULATION
418 PHP_METHOD(Geometry, delaunayTriangulation);
419 #endif
420
421 #ifdef HAVE_GEOS_VORONOI_DIAGRAM
422 PHP_METHOD(Geometry, voronoiDiagram);
423 #endif
424
425 #ifdef HAVE_GEOS_CLIP_BY_RECT
426 PHP_METHOD(Geometry, clipByRect);
427 #endif
428
429 static zend_function_entry Geometry_methods[] = {
430 PHP_ME(Geometry, __construct, NULL, 0)
431 PHP_ME(Geometry, __toString, NULL, 0)
432 PHP_ME(Geometry, project, NULL, 0)
433 PHP_ME(Geometry, interpolate, NULL, 0)
434 PHP_ME(Geometry, buffer, NULL, 0)
435
436 # ifdef HAVE_GEOS_OFFSET_CURVE
437 PHP_ME(Geometry, offsetCurve, NULL, 0)
438 # endif
439
440 PHP_ME(Geometry, envelope, NULL, 0)
441 PHP_ME(Geometry, intersection, NULL, 0)
442 PHP_ME(Geometry, convexHull, NULL, 0)
443 PHP_ME(Geometry, difference, NULL, 0)
444 PHP_ME(Geometry, symDifference, NULL, 0)
445 PHP_ME(Geometry, boundary, NULL, 0)
446 PHP_ME(Geometry, union, NULL, 0)
447 PHP_ME(Geometry, pointOnSurface, NULL, 0)
448 PHP_ME(Geometry, centroid, NULL, 0)
449 PHP_ME(Geometry, relate, NULL, 0)
450
451 # ifdef HAVE_GEOS_RELATE_BOUNDARY_NODE_RULE
452 PHP_ME(Geometry, relateBoundaryNodeRule, NULL, 0)
453 # endif
454
455 PHP_ME(Geometry, simplify, NULL, 0)
456 PHP_ME(Geometry, normalize, NULL, 0)
457
458 # ifdef HAVE_GEOS_GEOM_SET_PRECISION
459 PHP_ME(Geometry, setPrecision, NULL, 0)
460 # endif
461
462 # if HAVE_GEOS_GEOM_GET_PRECISION
463 PHP_ME(Geometry, getPrecision, NULL, 0)
464 # endif
465
466 # ifdef HAVE_GEOS_GEOM_EXTRACT_UNIQUE_POINTS
467 PHP_ME(Geometry, extractUniquePoints, NULL, 0)
468 # endif
469
470 PHP_ME(Geometry, disjoint, NULL, 0)
471 PHP_ME(Geometry, touches, NULL, 0)
472 PHP_ME(Geometry, intersects, NULL, 0)
473 PHP_ME(Geometry, crosses, NULL, 0)
474 PHP_ME(Geometry, within, NULL, 0)
475 PHP_ME(Geometry, contains, NULL, 0)
476 PHP_ME(Geometry, overlaps, NULL, 0)
477
478 # ifdef HAVE_GEOS_COVERS
479 PHP_ME(Geometry, covers, NULL, 0)
480 # endif
481
482 # ifdef HAVE_GEOS_COVERED_BY
483 PHP_ME(Geometry, coveredBy, NULL, 0)
484 # endif
485
486 PHP_ME(Geometry, equals, NULL, 0)
487 PHP_ME(Geometry, equalsExact, NULL, 0)
488 PHP_ME(Geometry, isEmpty, NULL, 0)
489
490 # ifdef HAVE_GEOS_IS_VALID_DETAIL
491 PHP_ME(Geometry, checkValidity, NULL, 0)
492 # endif
493
494 PHP_ME(Geometry, isSimple, NULL, 0)
495 PHP_ME(Geometry, isRing, NULL, 0)
496 PHP_ME(Geometry, hasZ, NULL, 0)
497
498 # ifdef HAVE_GEOS_IS_CLOSED
499 PHP_ME(Geometry, isClosed, NULL, 0)
500 # endif
501
502 PHP_ME(Geometry, typeName, NULL, 0)
503 PHP_ME(Geometry, typeId, NULL, 0)
504 PHP_ME(Geometry, getSRID, NULL, 0)
505 PHP_ME(Geometry, setSRID, NULL, 0)
506 PHP_ME(Geometry, numGeometries, NULL, 0)
507 PHP_ME(Geometry, geometryN, NULL, 0)
508 PHP_ME(Geometry, numInteriorRings, NULL, 0)
509
510 # ifdef HAVE_GEOS_GEOM_GET_NUM_POINTS
511 PHP_ME(Geometry, numPoints, NULL, 0)
512 # endif
513
514 # ifdef HAVE_GEOS_GEOM_GET_X
515 PHP_ME(Geometry, getX, NULL, 0)
516 # endif
517
518 # ifdef HAVE_GEOS_GEOM_GET_Y
519 PHP_ME(Geometry, getY, NULL, 0)
520 # endif
521
522 PHP_ME(Geometry, interiorRingN, NULL, 0)
523 PHP_ME(Geometry, exteriorRing, NULL, 0)
524 PHP_ME(Geometry, numCoordinates, NULL, 0)
525 PHP_ME(Geometry, dimension, NULL, 0)
526
527 # ifdef HAVE_GEOS_GEOM_GET_COORDINATE_DIMENSION
528 PHP_ME(Geometry, coordinateDimension, NULL, 0)
529 # endif
530
531 # ifdef HAVE_GEOS_GEOM_GET_POINT_N
532 PHP_ME(Geometry, pointN, NULL, 0)
533 # endif
534
535 # ifdef HAVE_GEOS_GEOM_GET_START_POINT
536 PHP_ME(Geometry, startPoint, NULL, 0)
537 # endif
538
539 # ifdef HAVE_GEOS_GEOM_GET_END_POINT
540 PHP_ME(Geometry, endPoint, NULL, 0)
541 # endif
542
543 PHP_ME(Geometry, area, NULL, 0)
544 PHP_ME(Geometry, length, NULL, 0)
545 PHP_ME(Geometry, distance, NULL, 0)
546 PHP_ME(Geometry, hausdorffDistance, NULL, 0)
547
548 # if HAVE_GEOS_SNAP
549 PHP_ME(Geometry, snapTo, NULL, 0)
550 # endif
551
552 # ifdef HAVE_GEOS_NODE
553 PHP_ME(Geometry, node, NULL, 0)
554 # endif
555
556 # ifdef HAVE_GEOS_DELAUNAY_TRIANGULATION
557 PHP_ME(Geometry, delaunayTriangulation, NULL, 0)
558 # endif
559
560 # ifdef HAVE_GEOS_VORONOI_DIAGRAM
561 PHP_ME(Geometry, voronoiDiagram, NULL, 0)
562 # endif
563
564 # ifdef HAVE_GEOS_CLIP_BY_RECT
565 PHP_ME(Geometry, clipByRect, NULL, 0)
566 # endif
567
568 {NULL, NULL, NULL}
569 };
570
571 static zend_class_entry *Geometry_ce_ptr;
572
573 static zend_object_handlers Geometry_object_handlers;
574
575 /* Geometry serializer */
576
577 static GEOSWKBWriter* Geometry_serializer = 0;
578
getGeometrySerializer()579 static GEOSWKBWriter* getGeometrySerializer()
580 {
581 TSRMLS_FETCH();
582
583 if ( ! Geometry_serializer ) {
584 Geometry_serializer = GEOSWKBWriter_create_r(GEOS_G(handle));
585 GEOSWKBWriter_setIncludeSRID_r(GEOS_G(handle), Geometry_serializer, 1);
586 GEOSWKBWriter_setOutputDimension_r(GEOS_G(handle), Geometry_serializer, 3);
587 }
588 return Geometry_serializer;
589 }
590
delGeometrySerializer()591 static void delGeometrySerializer()
592 {
593 TSRMLS_FETCH();
594
595 if ( Geometry_serializer ) {
596 GEOSWKBWriter_destroy_r(GEOS_G(handle), Geometry_serializer);
597 }
598 }
599
600 /* Geometry deserializer */
601
602 static GEOSWKBReader* Geometry_deserializer = 0;
603
getGeometryDeserializer()604 static GEOSWKBReader* getGeometryDeserializer()
605 {
606 TSRMLS_FETCH();
607
608 if ( ! Geometry_deserializer ) {
609 Geometry_deserializer = GEOSWKBReader_create_r(GEOS_G(handle));
610 }
611 return Geometry_deserializer;
612 }
613
delGeometryDeserializer()614 static void delGeometryDeserializer()
615 {
616 TSRMLS_FETCH();
617
618 if ( Geometry_deserializer ) {
619 GEOSWKBReader_destroy_r(GEOS_G(handle), Geometry_deserializer);
620 }
621 }
622
623 /* Serializer function for GEOSGeometry */
624
625 static int
Geometry_serialize(zval * object,unsigned char ** buffer,zend_uint * buf_len,zend_serialize_data * data TSRMLS_DC)626 Geometry_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len,
627 zend_serialize_data *data TSRMLS_DC)
628 {
629 GEOSWKBWriter *serializer;
630 GEOSGeometry *geom;
631 char* ret;
632 size_t retsize;
633
634
635 serializer = getGeometrySerializer();
636 geom = (GEOSGeometry*)getRelay(object, Geometry_ce_ptr);
637
638 /* NOTE: we might be fine using binary here */
639 ret = (char*)GEOSWKBWriter_writeHEX_r(GEOS_G(handle), serializer, geom, &retsize);
640 /* we'll probably get an exception if ret is null */
641 if ( ! ret ) return FAILURE;
642
643 *buffer = (unsigned char*)estrndup(ret, retsize);
644 GEOSFree_r(GEOS_G(handle), ret);
645
646 *buf_len = retsize;
647
648 return SUCCESS;
649 }
650
651 static int
Geometry_deserialize(GEOS_PHP_ZVAL object,zend_class_entry * ce,const unsigned char * buf,zend_uint buf_len,zend_unserialize_data * data TSRMLS_DC)652 Geometry_deserialize(GEOS_PHP_ZVAL object, zend_class_entry *ce, const unsigned char *buf,
653 zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
654 {
655 GEOSWKBReader* deserializer;
656 GEOSGeometry* geom;
657
658 deserializer = getGeometryDeserializer();
659 geom = GEOSWKBReader_readHEX_r(GEOS_G(handle), deserializer, buf, buf_len);
660
661 /* check zend_class_entry being what we expect! */
662 if ( ce != Geometry_ce_ptr ) {
663 php_error_docref(NULL TSRMLS_CC, E_ERROR,
664 "Geometry_deserialize called with unexpected zend_class_entry");
665 return FAILURE;
666 }
667 #if PHP_VERSION_ID >= 70000
668 object_init_ex(object, ce);
669 setRelay(object, geom);
670 #else
671 object_init_ex(*object, ce);
672 setRelay(*object, geom);
673 #endif
674
675 return SUCCESS;
676 }
677
678 /*
679 * Push components of the given geometry
680 * to the given array zval.
681 * Components geometries are cloned.
682 * NOTE: collection components are not descended into
683 */
684 static void
dumpGeometry(GEOSGeometry * g,zval * array)685 dumpGeometry(GEOSGeometry* g, zval* array)
686 {
687 TSRMLS_FETCH();
688 int ngeoms, i;
689
690 ngeoms = GEOSGetNumGeometries_r(GEOS_G(handle), g);
691 for (i=0; i<ngeoms; ++i)
692 {
693 zval *tmp;
694 GEOSGeometry* cc;
695 const GEOSGeometry* c = GEOSGetGeometryN_r(GEOS_G(handle), g, i);
696 if ( ! c ) continue; /* should get an exception */
697 /* we _need_ to clone as this one is owned by 'g' */
698 cc = GEOSGeom_clone_r(GEOS_G(handle), c);
699 if ( ! cc ) continue; /* should get an exception */
700
701 MAKE_STD_ZVAL(tmp);
702 object_init_ex(tmp, Geometry_ce_ptr);
703 setRelay(tmp, cc);
704 add_next_index_zval(array, tmp);
705 #if PHP_VERSION_ID >= 70000
706 efree(tmp);
707 #endif
708 }
709 }
710
711
712 static void
Geometry_dtor(GEOS_PHP_DTOR_OBJECT * object TSRMLS_DC)713 Geometry_dtor (GEOS_PHP_DTOR_OBJECT *object TSRMLS_DC)
714 {
715 #if PHP_VERSION_ID < 70000
716 Proxy *obj = (Proxy *)object;
717 #else
718 Proxy *obj = php_geos_fetch_object(object);
719 #endif
720
721 GEOSGeom_destroy_r(GEOS_G(handle), (GEOSGeometry*)obj->relay);
722
723 #if PHP_VERSION_ID >= 70000
724 //zend_object_std_dtor(&obj->std);
725 #else
726 zend_hash_destroy(obj->std.properties);
727 FREE_HASHTABLE(obj->std.properties);
728
729 efree(obj);
730 #endif
731 }
732
733 static zend_object_value
Geometry_create_obj(zend_class_entry * type TSRMLS_DC)734 Geometry_create_obj (zend_class_entry *type TSRMLS_DC)
735 {
736 return Gen_create_obj(type, Geometry_dtor, &Geometry_object_handlers);
737 }
738
739
PHP_METHOD(Geometry,__construct)740 PHP_METHOD(Geometry, __construct)
741 {
742 php_error_docref(NULL TSRMLS_CC, E_ERROR,
743 "GEOSGeometry can't be constructed using new, check WKTReader");
744
745 }
746
PHP_METHOD(Geometry,__toString)747 PHP_METHOD(Geometry, __toString)
748 {
749 GEOSGeometry *geom;
750 GEOSWKTWriter *writer;
751 char *wkt;
752 char *ret;
753
754 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
755 writer = GEOSWKTWriter_create_r(GEOS_G(handle));
756 /* NOTE: if we get an exception before reaching
757 * GEOSWKTWriter_destory below we'll be leaking memory.
758 * One fix could be storing the object in a refcounted
759 * zval.
760 */
761 # ifdef HAVE_GEOS_WKT_WRITER_SET_TRIM
762 GEOSWKTWriter_setTrim_r(GEOS_G(handle), writer, 1);
763 # endif
764
765 wkt = GEOSWKTWriter_write_r(GEOS_G(handle), writer, geom);
766 /* we'll probably get an exception if wkt is null */
767 if ( ! wkt ) RETURN_NULL();
768
769 GEOSWKTWriter_destroy_r(GEOS_G(handle), writer);
770
771
772 ret = estrdup(wkt);
773 GEOSFree_r(GEOS_G(handle), wkt);
774
775 GEOS_PHP_RETURN_STRING(ret);
776 }
777
PHP_METHOD(Geometry,project)778 PHP_METHOD(Geometry, project)
779 {
780 GEOSGeometry *this;
781 GEOSGeometry *other;
782 zval *zobj;
783 zend_bool normalized = 0;
784 double ret;
785
786 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
787
788 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|b", &zobj,
789 &normalized) == FAILURE) {
790 RETURN_NULL();
791 }
792 other = getRelay(zobj, Geometry_ce_ptr);
793
794 if ( normalized ) {
795 ret = GEOSProjectNormalized_r(GEOS_G(handle), this, other);
796 } else {
797 ret = GEOSProject_r(GEOS_G(handle), this, other);
798 }
799 if ( ret < 0 ) RETURN_NULL(); /* should get an exception first */
800
801 RETURN_DOUBLE(ret);
802 }
803
PHP_METHOD(Geometry,interpolate)804 PHP_METHOD(Geometry, interpolate)
805 {
806 GEOSGeometry *this;
807 double dist;
808 GEOSGeometry *ret;
809 zend_bool normalized = 0;
810
811 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
812
813 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|b",
814 &dist, &normalized) == FAILURE) {
815 RETURN_NULL();
816 }
817
818 if ( normalized ) {
819 ret = GEOSInterpolateNormalized_r(GEOS_G(handle), this, dist);
820 } else {
821 ret = GEOSInterpolate_r(GEOS_G(handle), this, dist);
822 }
823 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
824
825 /* return_value is a zval */
826 object_init_ex(return_value, Geometry_ce_ptr);
827 setRelay(return_value, ret);
828 }
829
830 /**
831 * GEOSGeometry::buffer(dist, [<styleArray>])
832 *
833 * styleArray keys supported:
834 * 'quad_segs'
835 * Type: int
836 * Number of segments used to approximate
837 * a quarter circle (defaults to 8).
838 * 'endcap'
839 * Type: long
840 * Endcap style (defaults to GEOSBUF_CAP_ROUND)
841 * 'join'
842 * Type: long
843 * Join style (defaults to GEOSBUF_JOIN_ROUND)
844 * 'mitre_limit'
845 * Type: double
846 * mitre ratio limit (only affects joins with GEOSBUF_JOIN_MITRE style)
847 * 'miter_limit' is also accepted as a synonym for 'mitre_limit'.
848 * 'single_sided'
849 * Type: bool
850 * If true buffer lines only on one side, so that the input line
851 * will be a portion of the boundary of the returned polygon.
852 * Only applies to lineal input. Defaults to false.
853 */
PHP_METHOD(Geometry,buffer)854 PHP_METHOD(Geometry, buffer)
855 {
856 GEOSGeometry *this;
857 double dist;
858 GEOSGeometry *ret;
859 GEOSBufferParams *params;
860 static const double default_mitreLimit = 5.0;
861 static const int default_endCapStyle = GEOSBUF_CAP_ROUND;
862 static const int default_joinStyle = GEOSBUF_JOIN_ROUND;
863 static const int default_quadSegs = 8;
864 long int quadSegs = default_quadSegs;
865 long int endCapStyle = default_endCapStyle;
866 long int joinStyle = default_joinStyle;
867 double mitreLimit = default_mitreLimit;
868 long singleSided = 0;
869 zval *style_val = NULL;
870 GEOS_PHP_ZVAL data;
871 HashTable *style;
872 zend_string *key;
873 zend_ulong index;
874
875 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
876
877 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|a",
878 &dist, &style_val) == FAILURE) {
879 RETURN_NULL();
880 }
881
882 params = GEOSBufferParams_create_r(GEOS_G(handle));
883
884 if ( style_val )
885 {
886 style = HASH_OF(style_val);
887 while(GEOS_PHP_HASH_GET_CUR_KEY(style, &key, &index)
888 == HASH_KEY_IS_STRING)
889 {
890 if(!strcmp(ZSTR_VAL(key), "quad_segs"))
891 {
892 GEOS_PHP_HASH_GET_CUR_DATA(style, data);
893 quadSegs = getZvalAsLong(data);
894 GEOSBufferParams_setQuadrantSegments_r(GEOS_G(handle), params, quadSegs);
895 }
896 else if(!strcmp(ZSTR_VAL(key), "endcap"))
897 {
898 GEOS_PHP_HASH_GET_CUR_DATA(style, data);
899 endCapStyle = getZvalAsLong(data);
900 GEOSBufferParams_setEndCapStyle_r(GEOS_G(handle), params, endCapStyle);
901 }
902 else if(!strcmp(ZSTR_VAL(key), "join"))
903 {
904 GEOS_PHP_HASH_GET_CUR_DATA(style, data);
905 joinStyle = getZvalAsLong(data);
906 GEOSBufferParams_setJoinStyle_r(GEOS_G(handle), params, joinStyle);
907 }
908 else if(!strcmp(ZSTR_VAL(key), "mitre_limit"))
909 {
910 GEOS_PHP_HASH_GET_CUR_DATA(style, data);
911 mitreLimit = getZvalAsDouble(data);
912 GEOSBufferParams_setMitreLimit_r(GEOS_G(handle), params, mitreLimit);
913 }
914 else if(!strcmp(ZSTR_VAL(key), "single_sided"))
915 {
916 GEOS_PHP_HASH_GET_CUR_DATA(style, data);
917 singleSided = getZvalAsLong(data);
918 GEOSBufferParams_setSingleSided_r(GEOS_G(handle), params, singleSided);
919 }
920
921 zend_hash_move_forward(style);
922 }
923 }
924
925 ret = GEOSBufferWithParams_r(GEOS_G(handle), this, params, dist);
926 GEOSBufferParams_destroy_r(GEOS_G(handle), params);
927 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
928
929 /* return_value is a zval */
930 object_init_ex(return_value, Geometry_ce_ptr);
931 setRelay(return_value, ret);
932 }
933
934 /**
935 * GEOSGeometry::offsetCurve(dist, [<styleArray>])
936 *
937 * styleArray keys supported:
938 * 'quad_segs'
939 * Type: int
940 * Number of segments used to approximate
941 * a quarter circle (defaults to 8).
942 * 'join'
943 * Type: long
944 * Join style (defaults to GEOSBUF_JOIN_ROUND)
945 * 'mitre_limit'
946 * Type: double
947 * mitre ratio limit (only affects joins with GEOSBUF_JOIN_MITRE style)
948 * 'miter_limit' is also accepted as a synonym for 'mitre_limit'.
949 */
950 #ifdef HAVE_GEOS_OFFSET_CURVE
PHP_METHOD(Geometry,offsetCurve)951 PHP_METHOD(Geometry, offsetCurve)
952 {
953 GEOSGeometry *this;
954 double dist;
955 GEOSGeometry *ret;
956 static const double default_mitreLimit = 5.0;
957 static const int default_joinStyle = GEOSBUF_JOIN_ROUND;
958 static const int default_quadSegs = 8;
959 long int quadSegs = default_quadSegs;
960 long int joinStyle = default_joinStyle;
961 double mitreLimit = default_mitreLimit;
962 zval *style_val = NULL;
963 GEOS_PHP_ZVAL data;
964 HashTable *style;
965 zend_string *key;
966 zend_ulong index;
967
968 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
969
970 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|a",
971 &dist, &style_val) == FAILURE) {
972 RETURN_NULL();
973 }
974
975 if ( style_val )
976 {
977 style = HASH_OF(style_val);
978 while(GEOS_PHP_HASH_GET_CUR_KEY(style, &key, &index)
979 == HASH_KEY_IS_STRING)
980 {
981 if(!strcmp(ZSTR_VAL(key), "quad_segs"))
982 {
983 GEOS_PHP_HASH_GET_CUR_DATA(style, data);
984 quadSegs = getZvalAsLong(data);
985 }
986 else if(!strcmp(ZSTR_VAL(key), "join"))
987 {
988 GEOS_PHP_HASH_GET_CUR_DATA(style, data);
989 joinStyle = getZvalAsLong(data);
990 }
991 else if(!strcmp(ZSTR_VAL(key), "mitre_limit"))
992 {
993 GEOS_PHP_HASH_GET_CUR_DATA(style, data);
994 mitreLimit = getZvalAsDouble(data);
995 }
996
997 zend_hash_move_forward(style);
998 }
999 }
1000
1001 ret = GEOSOffsetCurve_r(GEOS_G(handle), this, dist, quadSegs, joinStyle, mitreLimit);
1002 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1003
1004 /* return_value is a zval */
1005 object_init_ex(return_value, Geometry_ce_ptr);
1006 setRelay(return_value, ret);
1007 }
1008 #endif
1009
PHP_METHOD(Geometry,envelope)1010 PHP_METHOD(Geometry, envelope)
1011 {
1012 GEOSGeometry *this;
1013 GEOSGeometry *ret;
1014
1015 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1016
1017 ret = GEOSEnvelope_r(GEOS_G(handle), this);
1018 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1019
1020 /* return_value is a zval */
1021 object_init_ex(return_value, Geometry_ce_ptr);
1022 setRelay(return_value, ret);
1023 }
1024
PHP_METHOD(Geometry,intersection)1025 PHP_METHOD(Geometry, intersection)
1026 {
1027 GEOSGeometry *this;
1028 GEOSGeometry *other;
1029 GEOSGeometry *ret;
1030 zval *zobj;
1031
1032 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1033
1034 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1035 == FAILURE) {
1036 RETURN_NULL();
1037 }
1038 other = getRelay(zobj, Geometry_ce_ptr);
1039
1040 ret = GEOSIntersection_r(GEOS_G(handle), this, other);
1041 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1042
1043 /* return_value is a zval */
1044 object_init_ex(return_value, Geometry_ce_ptr);
1045 setRelay(return_value, ret);
1046 }
1047
1048 /**
1049 * GEOSGeometry GEOSGeometry::clipByRect(xmin,ymin,xmax,ymax)
1050 */
1051 #ifdef HAVE_GEOS_CLIP_BY_RECT
PHP_METHOD(Geometry,clipByRect)1052 PHP_METHOD(Geometry, clipByRect)
1053 {
1054 GEOSGeometry *this;
1055 GEOSGeometry *ret;
1056 double xmin,ymin,xmax,ymax;
1057
1058 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1059
1060 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddd",
1061 &xmin, &ymin, &xmax, &ymax) == FAILURE) {
1062 RETURN_NULL();
1063 }
1064
1065 ret = GEOSClipByRect_r(GEOS_G(handle), this, xmin, ymin, xmax, ymax);
1066 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1067
1068 /* return_value is a zval */
1069 object_init_ex(return_value, Geometry_ce_ptr);
1070 setRelay(return_value, ret);
1071 }
1072 #endif
1073
PHP_METHOD(Geometry,convexHull)1074 PHP_METHOD(Geometry, convexHull)
1075 {
1076 GEOSGeometry *this;
1077 GEOSGeometry *ret;
1078
1079 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1080
1081 ret = GEOSConvexHull_r(GEOS_G(handle), this);
1082 if ( ret == NULL ) RETURN_NULL(); /* should get an exception first */
1083
1084 /* return_value is a zval */
1085 object_init_ex(return_value, Geometry_ce_ptr);
1086 setRelay(return_value, ret);
1087 }
1088
PHP_METHOD(Geometry,difference)1089 PHP_METHOD(Geometry, difference)
1090 {
1091 GEOSGeometry *this;
1092 GEOSGeometry *other;
1093 GEOSGeometry *ret;
1094 zval *zobj;
1095
1096 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1097
1098 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1099 == FAILURE) {
1100 RETURN_NULL();
1101 }
1102 other = getRelay(zobj, Geometry_ce_ptr);
1103
1104 ret = GEOSDifference_r(GEOS_G(handle), this, other);
1105 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1106
1107 /* return_value is a zval */
1108 object_init_ex(return_value, Geometry_ce_ptr);
1109 setRelay(return_value, ret);
1110 }
1111
PHP_METHOD(Geometry,symDifference)1112 PHP_METHOD(Geometry, symDifference)
1113 {
1114 GEOSGeometry *this;
1115 GEOSGeometry *other;
1116 GEOSGeometry *ret;
1117 zval *zobj;
1118
1119 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1120
1121 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1122 == FAILURE) {
1123 RETURN_NULL();
1124 }
1125 other = getRelay(zobj, Geometry_ce_ptr);
1126
1127 ret = GEOSSymDifference_r(GEOS_G(handle), this, other);
1128 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1129
1130 /* return_value is a zval */
1131 object_init_ex(return_value, Geometry_ce_ptr);
1132 setRelay(return_value, ret);
1133 }
1134
PHP_METHOD(Geometry,boundary)1135 PHP_METHOD(Geometry, boundary)
1136 {
1137 GEOSGeometry *this;
1138 GEOSGeometry *ret;
1139
1140 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1141
1142 ret = GEOSBoundary_r(GEOS_G(handle), this);
1143 if ( ret == NULL ) RETURN_NULL(); /* should get an exception first */
1144
1145 /* return_value is a zval */
1146 object_init_ex(return_value, Geometry_ce_ptr);
1147 setRelay(return_value, ret);
1148 }
1149
1150 /**
1151 * GEOSGeometry::union(otherGeom)
1152 * GEOSGeometry::union()
1153 */
PHP_METHOD(Geometry,union)1154 PHP_METHOD(Geometry, union)
1155 {
1156 GEOSGeometry *this;
1157 GEOSGeometry *other;
1158 GEOSGeometry *ret;
1159 zval *zobj = NULL;
1160
1161 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1162
1163 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|o", &zobj)
1164 == FAILURE) {
1165 RETURN_NULL();
1166 }
1167
1168 if ( zobj ) {
1169 other = getRelay(zobj, Geometry_ce_ptr);
1170 ret = GEOSUnion_r(GEOS_G(handle), this, other);
1171 } else {
1172 # ifdef HAVE_GEOS_UNARY_UNION
1173 ret = GEOSUnaryUnion_r(GEOS_G(handle), this);
1174 # else
1175 ret = GEOSUnionCascaded_r(GEOS_G(handle), this);
1176 # endif
1177 }
1178
1179 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1180
1181 /* return_value is a zval */
1182 object_init_ex(return_value, Geometry_ce_ptr);
1183 setRelay(return_value, ret);
1184 }
1185
1186 /**
1187 * GEOSGeometry::pointOnSurface()
1188 */
PHP_METHOD(Geometry,pointOnSurface)1189 PHP_METHOD(Geometry, pointOnSurface)
1190 {
1191 GEOSGeometry *this;
1192 GEOSGeometry *ret;
1193
1194 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1195
1196 ret = GEOSPointOnSurface_r(GEOS_G(handle), this);
1197 if ( ret == NULL ) RETURN_NULL(); /* should get an exception first */
1198
1199 /* return_value is a zval */
1200 object_init_ex(return_value, Geometry_ce_ptr);
1201 setRelay(return_value, ret);
1202 }
1203
1204 /**
1205 * GEOSGeometry::centroid()
1206 */
PHP_METHOD(Geometry,centroid)1207 PHP_METHOD(Geometry, centroid)
1208 {
1209 GEOSGeometry *this;
1210 GEOSGeometry *ret;
1211
1212 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1213
1214 ret = GEOSGetCentroid_r(GEOS_G(handle), this);
1215 if ( ret == NULL ) RETURN_NULL(); /* should get an exception first */
1216
1217 /* return_value is a zval */
1218 object_init_ex(return_value, Geometry_ce_ptr);
1219 setRelay(return_value, ret);
1220 }
1221
1222 /**
1223 * GEOSGeometry::relate(otherGeom)
1224 * GEOSGeometry::relate(otherGeom, pattern)
1225 */
PHP_METHOD(Geometry,relate)1226 PHP_METHOD(Geometry, relate)
1227 {
1228 GEOSGeometry *this;
1229 GEOSGeometry *other;
1230 zval *zobj;
1231 char* pat = NULL;
1232 #if PHP_VERSION_ID >= 70000
1233 size_t patlen;
1234 #else
1235 int patlen;
1236 #endif
1237 int retInt;
1238 zend_bool retBool;
1239 char* retStr;
1240
1241 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1242
1243 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|s",
1244 &zobj, &pat, &patlen) == FAILURE)
1245 {
1246 RETURN_NULL();
1247 }
1248
1249 other = getRelay(zobj, Geometry_ce_ptr);
1250
1251 if ( ! pat ) {
1252 /* we'll compute it */
1253 pat = GEOSRelate_r(GEOS_G(handle), this, other);
1254 if ( ! pat ) RETURN_NULL(); /* should get an exception first */
1255 retStr = estrdup(pat);
1256 GEOSFree_r(GEOS_G(handle), pat);
1257 GEOS_PHP_RETURN_STRING(retStr);
1258 } else {
1259 retInt = GEOSRelatePattern_r(GEOS_G(handle), this, other, pat);
1260 if ( retInt == 2 ) RETURN_NULL(); /* should get an exception first */
1261 retBool = retInt;
1262 RETURN_BOOL(retBool);
1263 }
1264
1265 }
1266
1267 /**
1268 * GEOSGeometry::relateBoundaryNodeRule(otherGeom, rule)
1269 */
1270 #ifdef HAVE_GEOS_RELATE_BOUNDARY_NODE_RULE
PHP_METHOD(Geometry,relateBoundaryNodeRule)1271 PHP_METHOD(Geometry, relateBoundaryNodeRule)
1272 {
1273 GEOSGeometry *this;
1274 GEOSGeometry *other;
1275 zval *zobj;
1276 char* pat;
1277 long int bnr = GEOSRELATE_BNR_OGC;
1278 char* retStr;
1279
1280 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1281
1282 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ol",
1283 &zobj, &bnr) == FAILURE)
1284 {
1285 RETURN_NULL();
1286 }
1287
1288 other = getRelay(zobj, Geometry_ce_ptr);
1289
1290 /* we'll compute it */
1291 pat = GEOSRelateBoundaryNodeRule_r(GEOS_G(handle), this, other, bnr);
1292 if ( ! pat ) RETURN_NULL(); /* should get an exception first */
1293 retStr = estrdup(pat);
1294 GEOSFree_r(GEOS_G(handle), pat);
1295 GEOS_PHP_RETURN_STRING(retStr);
1296 }
1297 #endif
1298
1299 /**
1300 * GEOSGeometry GEOSGeometry::simplify(tolerance)
1301 * GEOSGeometry GEOSGeometry::simplify(tolerance, preserveTopology)
1302 */
PHP_METHOD(Geometry,simplify)1303 PHP_METHOD(Geometry, simplify)
1304 {
1305 GEOSGeometry *this;
1306 double tolerance;
1307 zend_bool preserveTopology = 0;
1308 GEOSGeometry *ret;
1309
1310 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1311
1312 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|b",
1313 &tolerance, &preserveTopology) == FAILURE) {
1314 RETURN_NULL();
1315 }
1316
1317 if ( preserveTopology ) {
1318 ret = GEOSTopologyPreserveSimplify_r(GEOS_G(handle), this, tolerance);
1319 } else {
1320 ret = GEOSSimplify_r(GEOS_G(handle), this, tolerance);
1321 }
1322
1323 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1324
1325 /* return_value is a zval */
1326 object_init_ex(return_value, Geometry_ce_ptr);
1327 setRelay(return_value, ret);
1328 }
1329
1330 /**
1331 * GEOSGeometry GEOSGeometry::setPrecision(gridsize, [flags])
1332 */
1333 #ifdef HAVE_GEOS_GEOM_SET_PRECISION
PHP_METHOD(Geometry,setPrecision)1334 PHP_METHOD(Geometry, setPrecision)
1335 {
1336 GEOSGeometry *this;
1337 double gridSize;
1338 long int flags = 0;
1339 GEOSGeometry *ret;
1340
1341 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1342
1343 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l",
1344 &gridSize, &flags) == FAILURE) {
1345 RETURN_NULL();
1346 }
1347
1348 ret = GEOSGeom_setPrecision_r(GEOS_G(handle), this, gridSize, flags);
1349
1350 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
1351
1352 /* return_value is a zval */
1353 object_init_ex(return_value, Geometry_ce_ptr);
1354 setRelay(return_value, ret);
1355 }
1356 #endif
1357
1358 /**
1359 * double GEOSGeometry::getPrecision()
1360 */
1361 #ifdef HAVE_GEOS_GEOM_GET_PRECISION
PHP_METHOD(Geometry,getPrecision)1362 PHP_METHOD(Geometry, getPrecision)
1363 {
1364 GEOSGeometry *geom;
1365 double prec;
1366
1367 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1368
1369 prec = GEOSGeom_getPrecision_r(GEOS_G(handle), geom);
1370 if ( prec < 0 ) RETURN_NULL(); /* should get an exception first */
1371
1372 RETURN_DOUBLE(prec);
1373 }
1374 #endif
1375
1376 /**
1377 * GEOSGeometry GEOSGeometry::normalize()
1378 */
PHP_METHOD(Geometry,normalize)1379 PHP_METHOD(Geometry, normalize)
1380 {
1381 GEOSGeometry *this;
1382 GEOSGeometry *ret;
1383
1384 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1385
1386 ret = GEOSGeom_clone_r(GEOS_G(handle), this);
1387
1388 if ( ! ret ) RETURN_NULL();
1389
1390 GEOSNormalize_r(GEOS_G(handle), ret); /* exception should be gotten automatically */
1391
1392 /* return_value is a zval */
1393 object_init_ex(return_value, Geometry_ce_ptr);
1394 setRelay(return_value, ret);
1395 }
1396
1397 /**
1398 * GEOSGeometry GEOSGeometry::extractUniquePoints()
1399 */
1400 #ifdef HAVE_GEOS_GEOM_EXTRACT_UNIQUE_POINTS
PHP_METHOD(Geometry,extractUniquePoints)1401 PHP_METHOD(Geometry, extractUniquePoints)
1402 {
1403 GEOSGeometry *this;
1404 GEOSGeometry *ret;
1405
1406 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1407
1408 ret = GEOSGeom_extractUniquePoints_r(GEOS_G(handle), this);
1409 if ( ret == NULL ) RETURN_NULL(); /* should get an exception first */
1410
1411 /* return_value is a zval */
1412 object_init_ex(return_value, Geometry_ce_ptr);
1413 setRelay(return_value, ret);
1414 }
1415 #endif
1416
1417 /**
1418 * bool GEOSGeometry::disjoint(GEOSGeometry)
1419 */
PHP_METHOD(Geometry,disjoint)1420 PHP_METHOD(Geometry, disjoint)
1421 {
1422 GEOSGeometry *this;
1423 GEOSGeometry *other;
1424 int ret;
1425 zend_bool retBool;
1426 zval *zobj;
1427
1428 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1429
1430 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1431 == FAILURE) {
1432 RETURN_NULL();
1433 }
1434 other = getRelay(zobj, Geometry_ce_ptr);
1435
1436 ret = GEOSDisjoint_r(GEOS_G(handle), this, other);
1437 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1438
1439 /* return_value is a zval */
1440 retBool = ret;
1441 RETURN_BOOL(retBool);
1442 }
1443
1444 /**
1445 * bool GEOSGeometry::touches(GEOSGeometry)
1446 */
PHP_METHOD(Geometry,touches)1447 PHP_METHOD(Geometry, touches)
1448 {
1449 GEOSGeometry *this;
1450 GEOSGeometry *other;
1451 int ret;
1452 zend_bool retBool;
1453 zval *zobj;
1454
1455 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1456
1457 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1458 == FAILURE) {
1459 RETURN_NULL();
1460 }
1461 other = getRelay(zobj, Geometry_ce_ptr);
1462
1463 ret = GEOSTouches_r(GEOS_G(handle), this, other);
1464 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1465
1466 /* return_value is a zval */
1467 retBool = ret;
1468 RETURN_BOOL(retBool);
1469 }
1470
1471 /**
1472 * bool GEOSGeometry::intersects(GEOSGeometry)
1473 */
PHP_METHOD(Geometry,intersects)1474 PHP_METHOD(Geometry, intersects)
1475 {
1476 GEOSGeometry *this;
1477 GEOSGeometry *other;
1478 int ret;
1479 zend_bool retBool;
1480 zval *zobj;
1481
1482 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1483
1484 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1485 == FAILURE) {
1486 RETURN_NULL();
1487 }
1488 other = getRelay(zobj, Geometry_ce_ptr);
1489
1490 ret = GEOSIntersects_r(GEOS_G(handle), this, other);
1491 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1492
1493 /* return_value is a zval */
1494 retBool = ret;
1495 RETURN_BOOL(retBool);
1496 }
1497
1498 /**
1499 * bool GEOSGeometry::crosses(GEOSGeometry)
1500 */
PHP_METHOD(Geometry,crosses)1501 PHP_METHOD(Geometry, crosses)
1502 {
1503 GEOSGeometry *this;
1504 GEOSGeometry *other;
1505 int ret;
1506 zend_bool retBool;
1507 zval *zobj;
1508
1509 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1510
1511 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1512 == FAILURE) {
1513 RETURN_NULL();
1514 }
1515 other = getRelay(zobj, Geometry_ce_ptr);
1516
1517 ret = GEOSCrosses_r(GEOS_G(handle), this, other);
1518 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1519
1520 /* return_value is a zval */
1521 retBool = ret;
1522 RETURN_BOOL(retBool);
1523 }
1524
1525 /**
1526 * bool GEOSGeometry::within(GEOSGeometry)
1527 */
PHP_METHOD(Geometry,within)1528 PHP_METHOD(Geometry, within)
1529 {
1530 GEOSGeometry *this;
1531 GEOSGeometry *other;
1532 int ret;
1533 zend_bool retBool;
1534 zval *zobj;
1535
1536 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1537
1538 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1539 == FAILURE) {
1540 RETURN_NULL();
1541 }
1542 other = getRelay(zobj, Geometry_ce_ptr);
1543
1544 ret = GEOSWithin_r(GEOS_G(handle), this, other);
1545 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1546
1547 /* return_value is a zval */
1548 retBool = ret;
1549 RETURN_BOOL(retBool);
1550 }
1551
1552 /**
1553 * bool GEOSGeometry::contains(GEOSGeometry)
1554 */
PHP_METHOD(Geometry,contains)1555 PHP_METHOD(Geometry, contains)
1556 {
1557 GEOSGeometry *this;
1558 GEOSGeometry *other;
1559 int ret;
1560 zend_bool retBool;
1561 zval *zobj;
1562
1563 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1564
1565 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1566 == FAILURE) {
1567 RETURN_NULL();
1568 }
1569 other = getRelay(zobj, Geometry_ce_ptr);
1570
1571 ret = GEOSContains_r(GEOS_G(handle), this, other);
1572 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1573
1574 /* return_value is a zval */
1575 retBool = ret;
1576 RETURN_BOOL(retBool);
1577 }
1578
1579 /**
1580 * bool GEOSGeometry::overlaps(GEOSGeometry)
1581 */
PHP_METHOD(Geometry,overlaps)1582 PHP_METHOD(Geometry, overlaps)
1583 {
1584 GEOSGeometry *this;
1585 GEOSGeometry *other;
1586 int ret;
1587 zend_bool retBool;
1588 zval *zobj;
1589
1590 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1591
1592 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1593 == FAILURE) {
1594 RETURN_NULL();
1595 }
1596 other = getRelay(zobj, Geometry_ce_ptr);
1597
1598 ret = GEOSOverlaps_r(GEOS_G(handle), this, other);
1599 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1600
1601 /* return_value is a zval */
1602 retBool = ret;
1603 RETURN_BOOL(retBool);
1604 }
1605
1606 /**
1607 * bool GEOSGeometry::covers(GEOSGeometry)
1608 */
1609 #ifdef HAVE_GEOS_COVERS
PHP_METHOD(Geometry,covers)1610 PHP_METHOD(Geometry, covers)
1611 {
1612 GEOSGeometry *this;
1613 GEOSGeometry *other;
1614 int ret;
1615 zend_bool retBool;
1616 zval *zobj;
1617
1618 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1619
1620 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1621 == FAILURE) {
1622 RETURN_NULL();
1623 }
1624 other = getRelay(zobj, Geometry_ce_ptr);
1625
1626 ret = GEOSCovers_r(GEOS_G(handle), this, other);
1627 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1628
1629 /* return_value is a zval */
1630 retBool = ret;
1631 RETURN_BOOL(retBool);
1632 }
1633 #endif
1634
1635 /**
1636 * bool GEOSGeometry::coveredBy(GEOSGeometry)
1637 */
1638 #ifdef HAVE_GEOS_COVERED_BY
PHP_METHOD(Geometry,coveredBy)1639 PHP_METHOD(Geometry, coveredBy)
1640 {
1641 GEOSGeometry *this;
1642 GEOSGeometry *other;
1643 int ret;
1644 zend_bool retBool;
1645 zval *zobj;
1646
1647 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1648
1649 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
1650 == FAILURE) {
1651 RETURN_NULL();
1652 }
1653 other = getRelay(zobj, Geometry_ce_ptr);
1654
1655 ret = GEOSCoveredBy_r(GEOS_G(handle), this, other);
1656 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1657
1658 /* return_value is a zval */
1659 retBool = ret;
1660 RETURN_BOOL(retBool);
1661 }
1662 #endif
1663
1664 /**
1665 * bool GEOSGeometry::equals(GEOSGeometry)
1666 */
PHP_METHOD(Geometry,equals)1667 PHP_METHOD(Geometry, equals)
1668 {
1669 GEOSGeometry *this;
1670 GEOSGeometry *other;
1671 int ret;
1672 zend_bool retBool;
1673 zval *zobj;
1674
1675 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1676
1677 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o",
1678 &zobj) == FAILURE) {
1679 RETURN_NULL();
1680 }
1681 other = getRelay(zobj, Geometry_ce_ptr);
1682
1683 ret = GEOSEquals_r(GEOS_G(handle), this, other);
1684 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1685
1686 /* return_value is a zval */
1687 retBool = ret;
1688 RETURN_BOOL(retBool);
1689 }
1690
1691 /**
1692 * bool GEOSGeometry::equalsExact(GEOSGeometry)
1693 * bool GEOSGeometry::equalsExact(GEOSGeometry, double tolerance)
1694 */
PHP_METHOD(Geometry,equalsExact)1695 PHP_METHOD(Geometry, equalsExact)
1696 {
1697 GEOSGeometry *this;
1698 GEOSGeometry *other;
1699 int ret;
1700 double tolerance = 0;
1701 zend_bool retBool;
1702 zval *zobj;
1703
1704 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1705
1706 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|d",
1707 &zobj, &tolerance) == FAILURE) {
1708 RETURN_NULL();
1709 }
1710 other = getRelay(zobj, Geometry_ce_ptr);
1711
1712 ret = GEOSEqualsExact_r(GEOS_G(handle), this, other, tolerance);
1713 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1714
1715 /* return_value is a zval */
1716 retBool = ret;
1717 RETURN_BOOL(retBool);
1718 }
1719
1720 /**
1721 * bool GEOSGeometry::isEmpty()
1722 */
PHP_METHOD(Geometry,isEmpty)1723 PHP_METHOD(Geometry, isEmpty)
1724 {
1725 GEOSGeometry *this;
1726 int ret;
1727 zend_bool retBool;
1728
1729 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1730
1731 ret = GEOSisEmpty_r(GEOS_G(handle), this);
1732 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1733
1734 /* return_value is a zval */
1735 retBool = ret;
1736 RETURN_BOOL(retBool);
1737 }
1738
1739 /**
1740 * array GEOSGeometry::checkValidity()
1741 */
1742 #ifdef HAVE_GEOS_IS_VALID_DETAIL
PHP_METHOD(Geometry,checkValidity)1743 PHP_METHOD(Geometry, checkValidity)
1744 {
1745 GEOSGeometry *this;
1746 GEOSGeometry *location = NULL;
1747 int ret;
1748 char *reason = NULL;
1749 zend_bool retBool;
1750 char *reasonVal = NULL;
1751 zval *locationVal = NULL;
1752 long int flags = 0;
1753
1754 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1755
1756 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l",
1757 &flags) == FAILURE) {
1758 RETURN_NULL();
1759 }
1760
1761 ret = GEOSisValidDetail_r(GEOS_G(handle), this, flags, &reason, &location);
1762 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1763
1764 if ( reason ) {
1765 reasonVal = estrdup(reason);
1766 GEOSFree_r(GEOS_G(handle), reason);
1767 }
1768
1769 if ( location ) {
1770 MAKE_STD_ZVAL(locationVal);
1771 object_init_ex(locationVal, Geometry_ce_ptr);
1772 setRelay(locationVal, location);
1773 }
1774
1775 retBool = ret;
1776
1777 /* return value is an array */
1778 array_init(return_value);
1779 add_assoc_bool(return_value, "valid", retBool);
1780 if ( reasonVal ) GEOS_PHP_ADD_ASSOC_ARRAY(return_value, "reason", reasonVal);
1781 if ( locationVal ) GEOS_PHP_ADD_ASSOC_ZVAL(return_value, "location", locationVal);
1782
1783 }
1784 #endif
1785
1786 /**
1787 * bool GEOSGeometry::isSimple()
1788 */
PHP_METHOD(Geometry,isSimple)1789 PHP_METHOD(Geometry, isSimple)
1790 {
1791 GEOSGeometry *this;
1792 int ret;
1793 zend_bool retBool;
1794
1795 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1796
1797 ret = GEOSisSimple_r(GEOS_G(handle), this);
1798 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1799
1800 /* return_value is a zval */
1801 retBool = ret;
1802 RETURN_BOOL(retBool);
1803 }
1804
1805 /**
1806 * bool GEOSGeometry::isRing()
1807 */
PHP_METHOD(Geometry,isRing)1808 PHP_METHOD(Geometry, isRing)
1809 {
1810 GEOSGeometry *this;
1811 int ret;
1812 zend_bool retBool;
1813
1814 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1815
1816 ret = GEOSisRing_r(GEOS_G(handle), this);
1817 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1818
1819 /* return_value is a zval */
1820 retBool = ret;
1821 RETURN_BOOL(retBool);
1822 }
1823
1824 /**
1825 * bool GEOSGeometry::hasZ()
1826 */
PHP_METHOD(Geometry,hasZ)1827 PHP_METHOD(Geometry, hasZ)
1828 {
1829 GEOSGeometry *this;
1830 int ret;
1831 zend_bool retBool;
1832
1833 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1834
1835 ret = GEOSHasZ_r(GEOS_G(handle), this);
1836 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1837
1838 /* return_value is a zval */
1839 retBool = ret;
1840 RETURN_BOOL(retBool);
1841 }
1842
1843 /**
1844 * bool GEOSGeometry::isClosed()
1845 */
1846 #ifdef HAVE_GEOS_IS_CLOSED
PHP_METHOD(Geometry,isClosed)1847 PHP_METHOD(Geometry, isClosed)
1848 {
1849 GEOSGeometry *this;
1850 int ret;
1851 zend_bool retBool;
1852
1853 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1854
1855 ret = GEOSisClosed_r(GEOS_G(handle), this);
1856 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
1857
1858 /* return_value is a zval */
1859 retBool = ret;
1860 RETURN_BOOL(retBool);
1861 }
1862 #endif
1863
1864 /**
1865 * string GEOSGeometry::typeName()
1866 */
PHP_METHOD(Geometry,typeName)1867 PHP_METHOD(Geometry, typeName)
1868 {
1869 GEOSGeometry *this;
1870 char *typ;
1871 char *typVal;
1872
1873 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1874
1875 /* TODO: define constant strings instead... */
1876
1877 typ = GEOSGeomType_r(GEOS_G(handle), this);
1878 if ( ! typ ) RETURN_NULL(); /* should get an exception first */
1879
1880 typVal = estrdup(typ);
1881 GEOSFree_r(GEOS_G(handle), typ);
1882
1883 GEOS_PHP_RETURN_STRING(typVal);
1884 }
1885
1886 /**
1887 * long GEOSGeometry::typeId()
1888 */
PHP_METHOD(Geometry,typeId)1889 PHP_METHOD(Geometry, typeId)
1890 {
1891 GEOSGeometry *this;
1892 long typ;
1893
1894 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1895
1896 /* TODO: define constant strings instead... */
1897
1898 typ = GEOSGeomTypeId_r(GEOS_G(handle), this);
1899 if ( typ == -1 ) RETURN_NULL(); /* should get an exception first */
1900
1901 RETURN_LONG(typ);
1902 }
1903
1904 /**
1905 * long GEOSGeometry::getSRID()
1906 */
PHP_METHOD(Geometry,getSRID)1907 PHP_METHOD(Geometry, getSRID)
1908 {
1909 GEOSGeometry *geom;
1910 long int ret;
1911
1912 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1913
1914 ret = GEOSGetSRID_r(GEOS_G(handle), geom);
1915
1916 RETURN_LONG(ret);
1917 }
1918
1919 /**
1920 * void GEOSGeometry::setSRID(long)
1921 */
PHP_METHOD(Geometry,setSRID)1922 PHP_METHOD(Geometry, setSRID)
1923 {
1924 GEOSGeometry *geom;
1925 long int srid;
1926
1927 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1928
1929 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
1930 &srid) == FAILURE) {
1931 RETURN_NULL();
1932 }
1933
1934 GEOSSetSRID_r(GEOS_G(handle), geom, srid);
1935 }
1936
1937 /**
1938 * long GEOSGeometry::numGeometries()
1939 */
PHP_METHOD(Geometry,numGeometries)1940 PHP_METHOD(Geometry, numGeometries)
1941 {
1942 GEOSGeometry *geom;
1943 long int ret;
1944
1945 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1946
1947 ret = GEOSGetNumGeometries_r(GEOS_G(handle), geom);
1948 if ( ret == -1 ) RETURN_NULL(); /* should get an exception first */
1949
1950 RETURN_LONG(ret);
1951 }
1952
1953 /**
1954 * GEOSGeometry GEOSGeometry::geometryN()
1955 */
PHP_METHOD(Geometry,geometryN)1956 PHP_METHOD(Geometry, geometryN)
1957 {
1958 GEOSGeometry *geom;
1959 const GEOSGeometry *c;
1960 GEOSGeometry *cc;
1961 long int num;
1962
1963 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1964
1965 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
1966 &num) == FAILURE) {
1967 RETURN_NULL();
1968 }
1969
1970 if ( num >= GEOSGetNumGeometries_r(GEOS_G(handle), geom) ) RETURN_NULL();
1971 c = GEOSGetGeometryN_r(GEOS_G(handle), geom, num);
1972 if ( ! c ) RETURN_NULL(); /* should get an exception first */
1973 cc = GEOSGeom_clone_r(GEOS_G(handle), c);
1974 if ( ! cc ) RETURN_NULL(); /* should get an exception first */
1975
1976 object_init_ex(return_value, Geometry_ce_ptr);
1977 setRelay(return_value, cc);
1978 }
1979
1980 /**
1981 * long GEOSGeometry::numInteriorRings()
1982 */
PHP_METHOD(Geometry,numInteriorRings)1983 PHP_METHOD(Geometry, numInteriorRings)
1984 {
1985 GEOSGeometry *geom;
1986 long int ret;
1987
1988 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
1989
1990 ret = GEOSGetNumInteriorRings_r(GEOS_G(handle), geom);
1991 if ( ret == -1 ) RETURN_NULL(); /* should get an exception first */
1992
1993 RETURN_LONG(ret);
1994 }
1995
1996 /**
1997 * long GEOSGeometry::numPoints()
1998 */
1999 #ifdef HAVE_GEOS_GEOM_GET_NUM_POINTS
PHP_METHOD(Geometry,numPoints)2000 PHP_METHOD(Geometry, numPoints)
2001 {
2002 GEOSGeometry *geom;
2003 long int ret;
2004
2005 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2006
2007 ret = GEOSGeomGetNumPoints_r(GEOS_G(handle), geom);
2008 if ( ret == -1 ) RETURN_NULL(); /* should get an exception first */
2009
2010 RETURN_LONG(ret);
2011 }
2012 #endif
2013
2014 /**
2015 * double GEOSGeometry::getX()
2016 */
2017 #ifdef HAVE_GEOS_GEOM_GET_X
PHP_METHOD(Geometry,getX)2018 PHP_METHOD(Geometry, getX)
2019 {
2020 GEOSGeometry *geom;
2021 int ret;
2022 double x;
2023
2024 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2025
2026 ret = GEOSGeomGetX_r(GEOS_G(handle), geom, &x);
2027 if ( ret == -1 ) RETURN_NULL(); /* should get an exception first */
2028
2029 RETURN_DOUBLE(x);
2030 }
2031 #endif
2032
2033 /**
2034 * double GEOSGeometry::getY()
2035 */
2036 #ifdef HAVE_GEOS_GEOM_GET_Y
PHP_METHOD(Geometry,getY)2037 PHP_METHOD(Geometry, getY)
2038 {
2039 GEOSGeometry *geom;
2040 int ret;
2041 double y;
2042
2043 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2044
2045 ret = GEOSGeomGetY_r(GEOS_G(handle), geom, &y);
2046 if ( ret == -1 ) RETURN_NULL(); /* should get an exception first */
2047
2048 RETURN_DOUBLE(y);
2049 }
2050 #endif
2051
2052 /**
2053 * GEOSGeometry GEOSGeometry::interiorRingN()
2054 */
PHP_METHOD(Geometry,interiorRingN)2055 PHP_METHOD(Geometry, interiorRingN)
2056 {
2057 GEOSGeometry *geom;
2058 const GEOSGeometry *c;
2059 GEOSGeometry *cc;
2060 long int num;
2061
2062 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2063
2064 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
2065 &num) == FAILURE) {
2066 RETURN_NULL();
2067 }
2068
2069 if ( num >= GEOSGetNumInteriorRings_r(GEOS_G(handle), geom) ) RETURN_NULL();
2070 c = GEOSGetInteriorRingN_r(GEOS_G(handle), geom, num);
2071 if ( ! c ) RETURN_NULL(); /* should get an exception first */
2072 cc = GEOSGeom_clone_r(GEOS_G(handle), c);
2073 if ( ! cc ) RETURN_NULL(); /* should get an exception first */
2074
2075 object_init_ex(return_value, Geometry_ce_ptr);
2076 setRelay(return_value, cc);
2077 }
2078
2079 /**
2080 * GEOSGeometry GEOSGeometry::exteriorRing()
2081 */
PHP_METHOD(Geometry,exteriorRing)2082 PHP_METHOD(Geometry, exteriorRing)
2083 {
2084 GEOSGeometry *geom;
2085 const GEOSGeometry *c;
2086 GEOSGeometry *cc;
2087
2088 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2089
2090 c = GEOSGetExteriorRing_r(GEOS_G(handle), geom);
2091 if ( ! c ) RETURN_NULL(); /* should get an exception first */
2092 cc = GEOSGeom_clone_r(GEOS_G(handle), c);
2093 if ( ! cc ) RETURN_NULL(); /* should get an exception first */
2094
2095 object_init_ex(return_value, Geometry_ce_ptr);
2096 setRelay(return_value, cc);
2097 }
2098
2099 /**
2100 * long GEOSGeometry::numCoordinates()
2101 */
PHP_METHOD(Geometry,numCoordinates)2102 PHP_METHOD(Geometry, numCoordinates)
2103 {
2104 GEOSGeometry *geom;
2105 long int ret;
2106
2107 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2108
2109 ret = GEOSGetNumCoordinates_r(GEOS_G(handle), geom);
2110 if ( ret == -1 ) RETURN_NULL(); /* should get an exception first */
2111
2112 RETURN_LONG(ret);
2113 }
2114
2115 /**
2116 * long GEOSGeometry::dimension()
2117 * 0:puntual 1:lineal 2:areal
2118 */
PHP_METHOD(Geometry,dimension)2119 PHP_METHOD(Geometry, dimension)
2120 {
2121 GEOSGeometry *geom;
2122 long int ret;
2123
2124 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2125
2126 ret = GEOSGeom_getDimensions_r(GEOS_G(handle), geom);
2127 if ( ret == -1 ) RETURN_NULL(); /* should get an exception first */
2128
2129 RETURN_LONG(ret);
2130 }
2131
2132 /**
2133 * long GEOSGeometry::coordinateDimension()
2134 */
2135 #ifdef HAVE_GEOS_GEOM_GET_COORDINATE_DIMENSION
PHP_METHOD(Geometry,coordinateDimension)2136 PHP_METHOD(Geometry, coordinateDimension)
2137 {
2138 GEOSGeometry *geom;
2139 long int ret;
2140
2141 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2142
2143 ret = GEOSGeom_getCoordinateDimension_r(GEOS_G(handle), geom);
2144 if ( ret == -1 ) RETURN_NULL(); /* should get an exception first */
2145
2146 RETURN_LONG(ret);
2147 }
2148 #endif
2149
2150 /**
2151 * GEOSGeometry GEOSGeometry::pointN()
2152 */
2153 #ifdef HAVE_GEOS_GEOM_GET_POINT_N
PHP_METHOD(Geometry,pointN)2154 PHP_METHOD(Geometry, pointN)
2155 {
2156 GEOSGeometry *geom;
2157 GEOSGeometry *c;
2158 long int num;
2159
2160 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2161
2162 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
2163 &num) == FAILURE) {
2164 RETURN_NULL();
2165 }
2166
2167 if ( num >= GEOSGeomGetNumPoints_r(GEOS_G(handle), geom) ) RETURN_NULL();
2168 c = GEOSGeomGetPointN_r(GEOS_G(handle), geom, num);
2169 if ( ! c ) RETURN_NULL(); /* should get an exception first */
2170
2171 object_init_ex(return_value, Geometry_ce_ptr);
2172 setRelay(return_value, c);
2173 }
2174 #endif
2175
2176 /**
2177 * GEOSGeometry GEOSGeometry::startPoint()
2178 */
PHP_METHOD(Geometry,startPoint)2179 PHP_METHOD(Geometry, startPoint)
2180 {
2181 GEOSGeometry *geom;
2182 GEOSGeometry *c;
2183
2184 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2185
2186 c = GEOSGeomGetStartPoint_r(GEOS_G(handle), geom);
2187 if ( ! c ) RETURN_NULL(); /* should get an exception first */
2188
2189 object_init_ex(return_value, Geometry_ce_ptr);
2190 setRelay(return_value, c);
2191 }
2192
2193 /**
2194 * GEOSGeometry GEOSGeometry::endPoint()
2195 */
PHP_METHOD(Geometry,endPoint)2196 PHP_METHOD(Geometry, endPoint)
2197 {
2198 GEOSGeometry *geom;
2199 GEOSGeometry *c;
2200
2201 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2202
2203 c = GEOSGeomGetEndPoint_r(GEOS_G(handle), geom);
2204 if ( ! c ) RETURN_NULL(); /* should get an exception first */
2205
2206 object_init_ex(return_value, Geometry_ce_ptr);
2207 setRelay(return_value, c);
2208 }
2209
2210 /**
2211 * double GEOSGeometry::area()
2212 */
PHP_METHOD(Geometry,area)2213 PHP_METHOD(Geometry, area)
2214 {
2215 GEOSGeometry *geom;
2216 double area;
2217 int ret;
2218
2219 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2220
2221 ret = GEOSArea_r(GEOS_G(handle), geom, &area);
2222 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
2223
2224 RETURN_DOUBLE(area);
2225 }
2226
2227 /**
2228 * double GEOSGeometry::length()
2229 */
PHP_METHOD(Geometry,length)2230 PHP_METHOD(Geometry, length)
2231 {
2232 GEOSGeometry *geom;
2233 double length;
2234 int ret;
2235
2236 geom = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2237
2238 ret = GEOSLength_r(GEOS_G(handle), geom, &length);
2239 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
2240
2241 RETURN_DOUBLE(length);
2242 }
2243
2244 /**
2245 * double GEOSGeometry::distance(GEOSGeometry)
2246 */
PHP_METHOD(Geometry,distance)2247 PHP_METHOD(Geometry, distance)
2248 {
2249 GEOSGeometry *this;
2250 GEOSGeometry *other;
2251 zval *zobj;
2252 double dist;
2253 int ret;
2254
2255 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2256
2257 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o",
2258 &zobj) == FAILURE)
2259 {
2260 RETURN_NULL();
2261 }
2262
2263 other = getRelay(zobj, Geometry_ce_ptr);
2264
2265 ret = GEOSDistance_r(GEOS_G(handle), this, other, &dist);
2266 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
2267
2268 RETURN_DOUBLE(dist);
2269 }
2270
2271 /**
2272 * double GEOSGeometry::hausdorffDistance(GEOSGeometry)
2273 */
PHP_METHOD(Geometry,hausdorffDistance)2274 PHP_METHOD(Geometry, hausdorffDistance)
2275 {
2276 GEOSGeometry *this;
2277 GEOSGeometry *other;
2278 zval *zobj;
2279 double dist;
2280 int ret;
2281
2282 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2283
2284 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o",
2285 &zobj) == FAILURE)
2286 {
2287 RETURN_NULL();
2288 }
2289
2290 other = getRelay(zobj, Geometry_ce_ptr);
2291
2292 ret = GEOSHausdorffDistance_r(GEOS_G(handle), this, other, &dist);
2293 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
2294
2295 RETURN_DOUBLE(dist);
2296 }
2297
2298 #ifdef HAVE_GEOS_SNAP
PHP_METHOD(Geometry,snapTo)2299 PHP_METHOD(Geometry, snapTo)
2300 {
2301 GEOSGeometry *this;
2302 GEOSGeometry *other;
2303 GEOSGeometry *ret;
2304 double tolerance;
2305 zval *zobj;
2306
2307 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2308
2309 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "od", &zobj,
2310 &tolerance) == FAILURE) {
2311 RETURN_NULL();
2312 }
2313 other = getRelay(zobj, Geometry_ce_ptr);
2314
2315 ret = GEOSSnap_r(GEOS_G(handle), this, other, tolerance);
2316 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
2317
2318 /* return_value is a zval */
2319 object_init_ex(return_value, Geometry_ce_ptr);
2320 setRelay(return_value, ret);
2321 }
2322 #endif
2323
2324 #ifdef HAVE_GEOS_NODE
PHP_METHOD(Geometry,node)2325 PHP_METHOD(Geometry, node)
2326 {
2327 GEOSGeometry *this;
2328 GEOSGeometry *ret;
2329
2330 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
2331
2332 ret = GEOSNode_r(GEOS_G(handle), this);
2333 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
2334
2335 /* return_value is a zval */
2336 object_init_ex(return_value, Geometry_ce_ptr);
2337 setRelay(return_value, ret);
2338 }
2339 #endif
2340
2341
2342
2343 /* -- class GEOSWKTReader -------------------- */
2344
2345 PHP_METHOD(WKTReader, __construct);
2346 PHP_METHOD(WKTReader, read);
2347
2348 static zend_function_entry WKTReader_methods[] = {
2349 PHP_ME(WKTReader, __construct, NULL, 0)
2350 PHP_ME(WKTReader, read, NULL, 0)
2351 {NULL, NULL, NULL}
2352 };
2353
2354 static zend_class_entry *WKTReader_ce_ptr;
2355
2356 static zend_object_handlers WKTReader_object_handlers;
2357
2358 static void
WKTReader_dtor(GEOS_PHP_DTOR_OBJECT * object TSRMLS_DC)2359 WKTReader_dtor (GEOS_PHP_DTOR_OBJECT *object TSRMLS_DC)
2360 {
2361 #if PHP_VERSION_ID < 70000
2362 Proxy *obj = (Proxy *)object;
2363 #else
2364 Proxy *obj = php_geos_fetch_object(object);
2365 #endif
2366
2367 GEOSWKTReader *reader = (GEOSWKTReader*)obj->relay;
2368 if (reader) {
2369 GEOSWKTReader_destroy_r(GEOS_G(handle), reader);
2370 }
2371
2372 #if PHP_VERSION_ID < 70000
2373 zend_hash_destroy(obj->std.properties);
2374 FREE_HASHTABLE(obj->std.properties);
2375
2376 efree(obj);
2377 #endif
2378 }
2379
2380 static zend_object_value
WKTReader_create_obj(zend_class_entry * type TSRMLS_DC)2381 WKTReader_create_obj (zend_class_entry *type TSRMLS_DC)
2382 {
2383 return Gen_create_obj(type, WKTReader_dtor, &WKTReader_object_handlers);
2384 }
2385
2386
PHP_METHOD(WKTReader,__construct)2387 PHP_METHOD(WKTReader, __construct)
2388 {
2389 GEOSWKTReader* obj;
2390 zval *object = getThis();
2391
2392 obj = GEOSWKTReader_create_r(GEOS_G(handle));
2393 if ( ! obj ) {
2394 php_error_docref(NULL TSRMLS_CC, E_ERROR,
2395 "GEOSWKTReader_create() failed (didn't initGEOS?)");
2396 }
2397
2398 setRelay(object, obj);
2399 }
2400
PHP_METHOD(WKTReader,read)2401 PHP_METHOD(WKTReader, read)
2402 {
2403 GEOSWKTReader *reader;
2404 GEOSGeometry *geom;
2405 zend_string *wkt;
2406 #if PHP_VERSION_ID < 70000
2407 int wktlen;
2408 #endif
2409
2410 reader = (GEOSWKTReader*)getRelay(getThis(), WKTReader_ce_ptr);
2411
2412 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
2413 #if PHP_VERSION_ID >= 70000
2414 "S", &wkt
2415 #else
2416 "s", &wkt, &wktlen
2417 #endif
2418 ) == FAILURE)
2419 {
2420 RETURN_NULL();
2421 }
2422
2423 geom = GEOSWKTReader_read_r(GEOS_G(handle), reader, ZSTR_VAL(wkt));
2424 /* we'll probably get an exception if geom is null */
2425 if ( ! geom ) RETURN_NULL();
2426
2427 /* return_value is a zval */
2428 object_init_ex(return_value, Geometry_ce_ptr);
2429 setRelay(return_value, geom);
2430
2431 }
2432
2433 /* -- class GEOSWKTWriter -------------------- */
2434
2435 PHP_METHOD(WKTWriter, __construct);
2436 PHP_METHOD(WKTWriter, write);
2437
2438 #ifdef HAVE_GEOS_WKT_WRITER_SET_TRIM
2439 PHP_METHOD(WKTWriter, setTrim);
2440 #endif
2441
2442 #ifdef HAVE_GEOS_WKT_WRITER_SET_ROUNDING_PRECISION
2443 PHP_METHOD(WKTWriter, setRoundingPrecision);
2444 #endif
2445
2446 #ifdef HAVE_GEOS_WKT_WRITER_SET_OUTPUT_DIMENSION
2447 PHP_METHOD(WKTWriter, setOutputDimension);
2448 #endif
2449
2450 #ifdef HAVE_GEOS_WKT_WRITER_GET_OUTPUT_DIMENSION
2451 PHP_METHOD(WKTWriter, getOutputDimension);
2452 #endif
2453
2454 #ifdef HAVE_GEOS_WKT_WRITER_SET_OLD_3D
2455 PHP_METHOD(WKTWriter, setOld3D);
2456 #endif
2457
2458 static zend_function_entry WKTWriter_methods[] = {
2459 PHP_ME(WKTWriter, __construct, NULL, 0)
2460 PHP_ME(WKTWriter, write, NULL, 0)
2461
2462 # ifdef HAVE_GEOS_WKT_WRITER_SET_TRIM
2463 PHP_ME(WKTWriter, setTrim, NULL, 0)
2464 # endif
2465
2466 # ifdef HAVE_GEOS_WKT_WRITER_SET_ROUNDING_PRECISION
2467 PHP_ME(WKTWriter, setRoundingPrecision, NULL, 0)
2468 # endif
2469
2470 # ifdef HAVE_GEOS_WKT_WRITER_SET_OUTPUT_DIMENSION
2471 PHP_ME(WKTWriter, setOutputDimension, NULL, 0)
2472 # endif
2473
2474 # ifdef HAVE_GEOS_WKT_WRITER_GET_OUTPUT_DIMENSION
2475 PHP_ME(WKTWriter, getOutputDimension, NULL, 0)
2476 # endif
2477
2478 # ifdef HAVE_GEOS_WKT_WRITER_SET_OLD_3D
2479 PHP_ME(WKTWriter, setOld3D, NULL, 0)
2480 # endif
2481
2482 {NULL, NULL, NULL}
2483 };
2484
2485 static zend_class_entry *WKTWriter_ce_ptr;
2486
2487 static zend_object_handlers WKTWriter_object_handlers;
2488
2489 static void
WKTWriter_dtor(GEOS_PHP_DTOR_OBJECT * object TSRMLS_DC)2490 WKTWriter_dtor (GEOS_PHP_DTOR_OBJECT *object TSRMLS_DC)
2491 {
2492 #if PHP_VERSION_ID < 70000
2493 Proxy *obj = (Proxy *)object;
2494 #else
2495 Proxy *obj = php_geos_fetch_object(object);
2496 #endif
2497
2498 GEOSWKTWriter_destroy_r(GEOS_G(handle), (GEOSWKTWriter*)obj->relay);
2499
2500 #if PHP_VERSION_ID >= 70000
2501 //zend_object_std_dtor(&obj->std);
2502 #else
2503 zend_hash_destroy(obj->std.properties);
2504 FREE_HASHTABLE(obj->std.properties);
2505
2506 efree(obj);
2507 #endif
2508 }
2509
2510 static zend_object_value
WKTWriter_create_obj(zend_class_entry * type TSRMLS_DC)2511 WKTWriter_create_obj (zend_class_entry *type TSRMLS_DC)
2512 {
2513 return Gen_create_obj(type, WKTWriter_dtor, &WKTWriter_object_handlers);
2514 }
2515
PHP_METHOD(WKTWriter,__construct)2516 PHP_METHOD(WKTWriter, __construct)
2517 {
2518 GEOSWKTWriter* obj;
2519 zval *object = getThis();
2520
2521 obj = GEOSWKTWriter_create_r(GEOS_G(handle));
2522 if ( ! obj ) {
2523 php_error_docref(NULL TSRMLS_CC, E_ERROR,
2524 "GEOSWKTWriter_create() failed (didn't initGEOS?)");
2525 }
2526
2527 setRelay(object, obj);
2528 }
2529
PHP_METHOD(WKTWriter,write)2530 PHP_METHOD(WKTWriter, write)
2531 {
2532 GEOSWKTWriter *writer;
2533 zval *zobj;
2534 GEOSGeometry *geom;
2535 char* wkt;
2536 char* retstr;
2537
2538 writer = (GEOSWKTWriter*)getRelay(getThis(), WKTWriter_ce_ptr);
2539
2540 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
2541 == FAILURE)
2542 {
2543 RETURN_NULL();
2544 }
2545
2546 geom = getRelay(zobj, Geometry_ce_ptr);
2547
2548 wkt = GEOSWKTWriter_write_r(GEOS_G(handle), writer, geom);
2549 /* we'll probably get an exception if wkt is null */
2550 if ( ! wkt ) RETURN_NULL();
2551
2552 retstr = estrdup(wkt);
2553 GEOSFree_r(GEOS_G(handle), wkt);
2554
2555 GEOS_PHP_RETURN_STRING(retstr);
2556 }
2557
2558 #ifdef HAVE_GEOS_WKT_WRITER_SET_TRIM
PHP_METHOD(WKTWriter,setTrim)2559 PHP_METHOD(WKTWriter, setTrim)
2560 {
2561 GEOSWKTWriter *writer;
2562 zend_bool trimval;
2563 char trim;
2564
2565 writer = (GEOSWKTWriter*)getRelay(getThis(), WKTWriter_ce_ptr);
2566
2567 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &trimval)
2568 == FAILURE)
2569 {
2570 RETURN_NULL();
2571 }
2572
2573 trim = trimval;
2574 GEOSWKTWriter_setTrim_r(GEOS_G(handle), writer, trim);
2575 }
2576 #endif
2577
2578 #ifdef HAVE_GEOS_WKT_WRITER_SET_ROUNDING_PRECISION
PHP_METHOD(WKTWriter,setRoundingPrecision)2579 PHP_METHOD(WKTWriter, setRoundingPrecision)
2580 {
2581 GEOSWKTWriter *writer;
2582 long int prec;
2583
2584 writer = (GEOSWKTWriter*)getRelay(getThis(), WKTWriter_ce_ptr);
2585
2586 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &prec)
2587 == FAILURE)
2588 {
2589 RETURN_NULL();
2590 }
2591
2592 GEOSWKTWriter_setRoundingPrecision_r(GEOS_G(handle), writer, prec);
2593 }
2594 #endif
2595
2596 /**
2597 * void GEOSWKTWriter::setOutputDimension()
2598 */
2599 #ifdef HAVE_GEOS_WKT_WRITER_SET_OUTPUT_DIMENSION
PHP_METHOD(WKTWriter,setOutputDimension)2600 PHP_METHOD(WKTWriter, setOutputDimension)
2601 {
2602 GEOSWKTWriter *writer;
2603 long int dim;
2604
2605 writer = (GEOSWKTWriter*)getRelay(getThis(), WKTWriter_ce_ptr);
2606
2607 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &dim)
2608 == FAILURE)
2609 {
2610 RETURN_NULL();
2611 }
2612
2613 GEOSWKTWriter_setOutputDimension_r(GEOS_G(handle), writer, dim);
2614 }
2615 #endif
2616
2617 /**
2618 * long GEOSWKTWriter::getOutputDimension()
2619 */
2620 #ifdef HAVE_GEOS_WKT_WRITER_GET_OUTPUT_DIMENSION
PHP_METHOD(WKTWriter,getOutputDimension)2621 PHP_METHOD(WKTWriter, getOutputDimension)
2622 {
2623 GEOSWKTWriter *writer;
2624 long int ret;
2625
2626 writer = (GEOSWKTWriter*)getRelay(getThis(), WKTWriter_ce_ptr);
2627
2628 ret = GEOSWKTWriter_getOutputDimension_r(GEOS_G(handle), writer);
2629
2630 RETURN_LONG(ret);
2631 }
2632 #endif
2633
2634 #ifdef HAVE_GEOS_WKT_WRITER_SET_OLD_3D
PHP_METHOD(WKTWriter,setOld3D)2635 PHP_METHOD(WKTWriter, setOld3D)
2636 {
2637 GEOSWKTWriter *writer;
2638 zend_bool bval;
2639 int val;
2640
2641 writer = (GEOSWKTWriter*)getRelay(getThis(), WKTWriter_ce_ptr);
2642
2643 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &bval)
2644 == FAILURE)
2645 {
2646 RETURN_NULL();
2647 }
2648
2649 val = bval;
2650 GEOSWKTWriter_setOld3D_r(GEOS_G(handle), writer, val);
2651 }
2652 #endif
2653
2654 /* -- class GEOSWKBWriter -------------------- */
2655
2656 PHP_METHOD(WKBWriter, __construct);
2657 PHP_METHOD(WKBWriter, getOutputDimension);
2658 PHP_METHOD(WKBWriter, setOutputDimension);
2659 PHP_METHOD(WKBWriter, getByteOrder);
2660 PHP_METHOD(WKBWriter, setByteOrder);
2661 PHP_METHOD(WKBWriter, setIncludeSRID);
2662 PHP_METHOD(WKBWriter, getIncludeSRID);
2663 PHP_METHOD(WKBWriter, write);
2664 PHP_METHOD(WKBWriter, writeHEX);
2665
2666 static zend_function_entry WKBWriter_methods[] = {
2667 PHP_ME(WKBWriter, __construct, NULL, 0)
2668 PHP_ME(WKBWriter, getOutputDimension, NULL, 0)
2669 PHP_ME(WKBWriter, setOutputDimension, NULL, 0)
2670 PHP_ME(WKBWriter, getByteOrder, NULL, 0)
2671 PHP_ME(WKBWriter, setByteOrder, NULL, 0)
2672 PHP_ME(WKBWriter, getIncludeSRID, NULL, 0)
2673 PHP_ME(WKBWriter, setIncludeSRID, NULL, 0)
2674 PHP_ME(WKBWriter, write, NULL, 0)
2675 PHP_ME(WKBWriter, writeHEX, NULL, 0)
2676 {NULL, NULL, NULL}
2677 };
2678
2679 static zend_class_entry *WKBWriter_ce_ptr;
2680
2681 static zend_object_handlers WKBWriter_object_handlers;
2682
2683 static void
WKBWriter_dtor(GEOS_PHP_DTOR_OBJECT * object TSRMLS_DC)2684 WKBWriter_dtor (GEOS_PHP_DTOR_OBJECT *object TSRMLS_DC)
2685 {
2686 #if PHP_VERSION_ID < 70000
2687 Proxy *obj = (Proxy *)object;
2688 #else
2689 Proxy *obj = php_geos_fetch_object(object);
2690 #endif
2691
2692 GEOSWKBWriter_destroy_r(GEOS_G(handle), (GEOSWKBWriter*)obj->relay);
2693
2694 #if PHP_VERSION_ID >= 70000
2695 //zend_object_std_dtor(&obj->std);
2696 #else
2697 zend_hash_destroy(obj->std.properties);
2698 FREE_HASHTABLE(obj->std.properties);
2699
2700 efree(obj);
2701 #endif
2702 }
2703
2704 static zend_object_value
WKBWriter_create_obj(zend_class_entry * type TSRMLS_DC)2705 WKBWriter_create_obj (zend_class_entry *type TSRMLS_DC)
2706 {
2707 return Gen_create_obj(type, WKBWriter_dtor, &WKBWriter_object_handlers);
2708 }
2709
2710 /**
2711 * GEOSWKBWriter w = new GEOSWKBWriter()
2712 */
PHP_METHOD(WKBWriter,__construct)2713 PHP_METHOD(WKBWriter, __construct)
2714 {
2715 GEOSWKBWriter* obj;
2716 zval *object = getThis();
2717
2718 obj = GEOSWKBWriter_create_r(GEOS_G(handle));
2719 if ( ! obj ) {
2720 php_error_docref(NULL TSRMLS_CC, E_ERROR,
2721 "GEOSWKBWriter_create() failed (didn't initGEOS?)");
2722 }
2723
2724 setRelay(object, obj);
2725 }
2726
2727 /**
2728 * long GEOSWKBWriter::getOutputDimension();
2729 */
PHP_METHOD(WKBWriter,getOutputDimension)2730 PHP_METHOD(WKBWriter, getOutputDimension)
2731 {
2732 GEOSWKBWriter *writer;
2733 long int ret;
2734
2735 writer = (GEOSWKBWriter*)getRelay(getThis(), WKBWriter_ce_ptr);
2736
2737 ret = GEOSWKBWriter_getOutputDimension_r(GEOS_G(handle), writer);
2738
2739 RETURN_LONG(ret);
2740 }
2741
2742 /**
2743 * void GEOSWKBWriter::setOutputDimension(dims);
2744 */
PHP_METHOD(WKBWriter,setOutputDimension)2745 PHP_METHOD(WKBWriter, setOutputDimension)
2746 {
2747 GEOSWKBWriter *writer;
2748 long int dim;
2749
2750 writer = (GEOSWKBWriter*)getRelay(getThis(), WKBWriter_ce_ptr);
2751
2752 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &dim)
2753 == FAILURE)
2754 {
2755 RETURN_NULL();
2756 }
2757
2758 GEOSWKBWriter_setOutputDimension_r(GEOS_G(handle), writer, dim);
2759
2760 }
2761
2762 /**
2763 * string GEOSWKBWriter::write(GEOSGeometry)
2764 */
PHP_METHOD(WKBWriter,write)2765 PHP_METHOD(WKBWriter, write)
2766 {
2767 GEOSWKBWriter *writer;
2768 zval *zobj;
2769 GEOSGeometry *geom;
2770 char *ret;
2771 size_t retsize;
2772 char* retstr;
2773
2774 writer = (GEOSWKBWriter*)getRelay(getThis(), WKBWriter_ce_ptr);
2775
2776 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
2777 == FAILURE)
2778 {
2779 RETURN_NULL();
2780 }
2781
2782 geom = getRelay(zobj, Geometry_ce_ptr);
2783
2784 ret = (char*)GEOSWKBWriter_write_r(GEOS_G(handle), writer, geom, &retsize);
2785 /* we'll probably get an exception if ret is null */
2786 if ( ! ret ) RETURN_NULL();
2787
2788 retstr = estrndup(ret, retsize);
2789 GEOSFree_r(GEOS_G(handle), ret);
2790
2791 GEOS_PHP_RETURN_STRINGL(retstr, retsize);
2792 }
2793
2794 /**
2795 * string GEOSWKBWriter::writeHEX(GEOSGeometry)
2796 */
PHP_METHOD(WKBWriter,writeHEX)2797 PHP_METHOD(WKBWriter, writeHEX)
2798 {
2799 GEOSWKBWriter *writer;
2800 zval *zobj;
2801 GEOSGeometry *geom;
2802 char *ret;
2803 size_t retsize; /* useless... */
2804 char* retstr;
2805
2806 writer = (GEOSWKBWriter*)getRelay(getThis(), WKBWriter_ce_ptr);
2807
2808 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
2809 == FAILURE)
2810 {
2811 RETURN_NULL();
2812 }
2813
2814 geom = getRelay(zobj, Geometry_ce_ptr);
2815
2816 ret = (char*)GEOSWKBWriter_writeHEX_r(GEOS_G(handle), writer, geom, &retsize);
2817 /* we'll probably get an exception if ret is null */
2818 if ( ! ret ) RETURN_NULL();
2819
2820 retstr = estrndup(ret, retsize);
2821 GEOSFree_r(GEOS_G(handle), ret);
2822
2823 GEOS_PHP_RETURN_STRING(retstr);
2824 }
2825
2826 /**
2827 * long GEOSWKBWriter::getByteOrder();
2828 */
PHP_METHOD(WKBWriter,getByteOrder)2829 PHP_METHOD(WKBWriter, getByteOrder)
2830 {
2831 GEOSWKBWriter *writer;
2832 long int ret;
2833
2834 writer = (GEOSWKBWriter*)getRelay(getThis(), WKBWriter_ce_ptr);
2835
2836 ret = GEOSWKBWriter_getByteOrder_r(GEOS_G(handle), writer);
2837
2838 RETURN_LONG(ret);
2839 }
2840
2841 /**
2842 * void GEOSWKBWriter::setByteOrder(dims);
2843 */
PHP_METHOD(WKBWriter,setByteOrder)2844 PHP_METHOD(WKBWriter, setByteOrder)
2845 {
2846 GEOSWKBWriter *writer;
2847 long int dim;
2848
2849 writer = (GEOSWKBWriter*)getRelay(getThis(), WKBWriter_ce_ptr);
2850
2851 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &dim)
2852 == FAILURE)
2853 {
2854 RETURN_NULL();
2855 }
2856
2857 GEOSWKBWriter_setByteOrder_r(GEOS_G(handle), writer, dim);
2858
2859 }
2860
2861 /**
2862 * bool GEOSWKBWriter::getIncludeSRID();
2863 */
PHP_METHOD(WKBWriter,getIncludeSRID)2864 PHP_METHOD(WKBWriter, getIncludeSRID)
2865 {
2866 GEOSWKBWriter *writer;
2867 int ret;
2868 zend_bool retBool;
2869
2870 writer = (GEOSWKBWriter*)getRelay(getThis(), WKBWriter_ce_ptr);
2871
2872 ret = GEOSWKBWriter_getIncludeSRID_r(GEOS_G(handle), writer);
2873 retBool = ret;
2874
2875 RETURN_BOOL(retBool);
2876 }
2877
2878 /**
2879 * void GEOSWKBWriter::setIncludeSRID(bool);
2880 */
PHP_METHOD(WKBWriter,setIncludeSRID)2881 PHP_METHOD(WKBWriter, setIncludeSRID)
2882 {
2883 GEOSWKBWriter *writer;
2884 int inc;
2885 zend_bool incVal;
2886
2887 writer = (GEOSWKBWriter*)getRelay(getThis(), WKBWriter_ce_ptr);
2888
2889 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &incVal)
2890 == FAILURE)
2891 {
2892 RETURN_NULL();
2893 }
2894
2895 inc = incVal;
2896 GEOSWKBWriter_setIncludeSRID_r(GEOS_G(handle), writer, inc);
2897 }
2898
2899 /* -- class GEOSWKBReader -------------------- */
2900
2901 PHP_METHOD(WKBReader, __construct);
2902 PHP_METHOD(WKBReader, read);
2903 PHP_METHOD(WKBReader, readHEX);
2904
2905 static zend_function_entry WKBReader_methods[] = {
2906 PHP_ME(WKBReader, __construct, NULL, 0)
2907 PHP_ME(WKBReader, read, NULL, 0)
2908 PHP_ME(WKBReader, readHEX, NULL, 0)
2909 {NULL, NULL, NULL}
2910 };
2911
2912 static zend_class_entry *WKBReader_ce_ptr;
2913
2914 static zend_object_handlers WKBReader_object_handlers;
2915
2916 static void
WKBReader_dtor(GEOS_PHP_DTOR_OBJECT * object TSRMLS_DC)2917 WKBReader_dtor (GEOS_PHP_DTOR_OBJECT *object TSRMLS_DC)
2918 {
2919 #if PHP_VERSION_ID < 70000
2920 Proxy *obj = (Proxy *)object;
2921 #else
2922 Proxy *obj = php_geos_fetch_object(object);
2923 #endif
2924
2925 GEOSWKBReader_destroy_r(GEOS_G(handle), (GEOSWKBReader*)obj->relay);
2926
2927 #if PHP_VERSION_ID >= 70000
2928 //zend_object_std_dtor(&obj->std);
2929 #else
2930 zend_hash_destroy(obj->std.properties);
2931 FREE_HASHTABLE(obj->std.properties);
2932
2933 efree(obj);
2934 #endif
2935 }
2936
2937 static zend_object_value
WKBReader_create_obj(zend_class_entry * type TSRMLS_DC)2938 WKBReader_create_obj (zend_class_entry *type TSRMLS_DC)
2939 {
2940 return Gen_create_obj(type, WKBReader_dtor, &WKBReader_object_handlers);
2941 }
2942
2943
PHP_METHOD(WKBReader,__construct)2944 PHP_METHOD(WKBReader, __construct)
2945 {
2946 GEOSWKBReader* obj;
2947 zval *object = getThis();
2948
2949 obj = GEOSWKBReader_create_r(GEOS_G(handle));
2950 if ( ! obj ) {
2951 php_error_docref(NULL TSRMLS_CC, E_ERROR,
2952 "GEOSWKBReader_create() failed (didn't initGEOS?)");
2953 }
2954
2955 setRelay(object, obj);
2956 }
2957
PHP_METHOD(WKBReader,read)2958 PHP_METHOD(WKBReader, read)
2959 {
2960 GEOSWKBReader *reader;
2961 GEOSGeometry *geom;
2962 zend_string* wkb;
2963 int wkblen;
2964
2965 reader = (GEOSWKBReader*)getRelay(getThis(), WKBReader_ce_ptr);
2966
2967 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
2968 #if PHP_VERSION_ID >= 70000
2969 "S", &wkb
2970 #else
2971 "s", &wkb, &wkblen
2972 #endif
2973 ) == FAILURE)
2974 {
2975 RETURN_NULL();
2976 }
2977
2978 #if PHP_VERSION_ID >= 70000
2979 wkblen = ZSTR_LEN(wkb);
2980 #endif
2981
2982 geom = GEOSWKBReader_read_r(GEOS_G(handle), reader, (unsigned char*)ZSTR_VAL(wkb), wkblen);
2983 /* we'll probably get an exception if geom is null */
2984 if ( ! geom ) RETURN_NULL();
2985
2986 /* return_value is a zval */
2987 object_init_ex(return_value, Geometry_ce_ptr);
2988 setRelay(return_value, geom);
2989
2990 }
2991
PHP_METHOD(WKBReader,readHEX)2992 PHP_METHOD(WKBReader, readHEX)
2993 {
2994 GEOSWKBReader *reader;
2995 GEOSGeometry *geom;
2996 unsigned char* wkb;
2997 #if PHP_VERSION_ID >= 70000
2998 size_t wkblen;
2999 #else
3000 int wkblen;
3001 #endif
3002
3003 reader = (GEOSWKBReader*)getRelay(getThis(), WKBReader_ce_ptr);
3004
3005 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
3006 &wkb, &wkblen) == FAILURE)
3007 {
3008 RETURN_NULL();
3009 }
3010
3011 geom = GEOSWKBReader_readHEX_r(GEOS_G(handle), reader, wkb, wkblen);
3012 /* we'll probably get an exception if geom is null */
3013 if ( ! geom ) RETURN_NULL();
3014
3015 /* return_value is a zval */
3016 object_init_ex(return_value, Geometry_ce_ptr);
3017 setRelay(return_value, geom);
3018
3019 }
3020
3021
3022 /* -- Free functions ------------------------- */
3023
3024 /**
3025 * string GEOSVersion()
3026 */
PHP_FUNCTION(GEOSVersion)3027 PHP_FUNCTION(GEOSVersion)
3028 {
3029 char *str;
3030
3031 str = estrdup(GEOSversion());
3032 GEOS_PHP_RETURN_STRING(str);
3033 }
3034
3035 /**
3036 * array GEOSPolygonize(GEOSGeometry $geom)
3037 *
3038 * The returned array contains the following elements:
3039 *
3040 * - 'rings'
3041 * Type: array of GEOSGeometry
3042 * Rings that can be formed by the costituent
3043 * linework of geometry.
3044 * - 'cut_edges' (optional)
3045 * Type: array of GEOSGeometry
3046 * Edges which are connected at both ends but
3047 * which do not form part of polygon.
3048 * - 'dangles'
3049 * Type: array of GEOSGeometry
3050 * Edges which have one or both ends which are
3051 * not incident on another edge endpoint
3052 * - 'invalid_rings'
3053 * Type: array of GEOSGeometry
3054 * Edges which form rings which are invalid
3055 * (e.g. the component lines contain a self-intersection)
3056 *
3057 */
PHP_FUNCTION(GEOSPolygonize)3058 PHP_FUNCTION(GEOSPolygonize)
3059 {
3060 GEOSGeometry *this;
3061 GEOSGeometry *rings;
3062 GEOSGeometry *cut_edges;
3063 GEOSGeometry *dangles;
3064 GEOSGeometry *invalid_rings;
3065 zval *array_elem;
3066 zval *zobj;
3067
3068 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
3069 == FAILURE)
3070 {
3071 RETURN_NULL();
3072 }
3073 this = getRelay(zobj, Geometry_ce_ptr);
3074
3075 rings = GEOSPolygonize_full_r(GEOS_G(handle), this, &cut_edges, &dangles, &invalid_rings);
3076 if ( ! rings ) RETURN_NULL(); /* should get an exception first */
3077
3078 /* return value should be an array */
3079 array_init(return_value);
3080
3081 MAKE_STD_ZVAL(array_elem);
3082 array_init(array_elem);
3083 dumpGeometry(rings, array_elem);
3084 GEOSGeom_destroy_r(GEOS_G(handle), rings);
3085 GEOS_PHP_ADD_ASSOC_ZVAL(return_value, "rings", array_elem);
3086
3087 MAKE_STD_ZVAL(array_elem);
3088 array_init(array_elem);
3089 dumpGeometry(cut_edges, array_elem);
3090 GEOSGeom_destroy_r(GEOS_G(handle), cut_edges);
3091 GEOS_PHP_ADD_ASSOC_ZVAL(return_value, "cut_edges", array_elem);
3092
3093 MAKE_STD_ZVAL(array_elem);
3094 array_init(array_elem);
3095 dumpGeometry(dangles, array_elem);
3096 GEOSGeom_destroy_r(GEOS_G(handle), dangles);
3097 GEOS_PHP_ADD_ASSOC_ZVAL(return_value, "dangles", array_elem);
3098
3099 MAKE_STD_ZVAL(array_elem);
3100 array_init(array_elem);
3101 dumpGeometry(invalid_rings, array_elem);
3102 GEOSGeom_destroy_r(GEOS_G(handle), invalid_rings);
3103 GEOS_PHP_ADD_ASSOC_ZVAL(return_value, "invalid_rings", array_elem);
3104
3105 }
3106
3107 /**
3108 * array GEOSLineMerge(GEOSGeometry $geom)
3109 */
PHP_FUNCTION(GEOSLineMerge)3110 PHP_FUNCTION(GEOSLineMerge)
3111 {
3112 GEOSGeometry *geom_in;
3113 GEOSGeometry *geom_out;
3114 zval *zobj;
3115
3116 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zobj)
3117 == FAILURE)
3118 {
3119 RETURN_NULL();
3120 }
3121 geom_in = getRelay(zobj, Geometry_ce_ptr);
3122
3123 geom_out = GEOSLineMerge_r(GEOS_G(handle), geom_in);
3124 if ( ! geom_out ) RETURN_NULL(); /* should get an exception first */
3125
3126 /* return value should be an array */
3127 array_init(return_value);
3128 dumpGeometry(geom_out, return_value);
3129 GEOSGeom_destroy_r(GEOS_G(handle), geom_out);
3130 }
3131
3132 /**
3133 * GEOSGeometry GEOSSharedPaths(GEOSGeometry $geom1, GEOSGeometry *geom2)
3134 */
3135 #ifdef HAVE_GEOS_SHARED_PATHS
PHP_FUNCTION(GEOSSharedPaths)3136 PHP_FUNCTION(GEOSSharedPaths)
3137 {
3138 GEOSGeometry *geom_in_1;
3139 GEOSGeometry *geom_in_2;
3140 GEOSGeometry *geom_out;
3141 zval *zobj1, *zobj2;
3142
3143 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oo", &zobj1, &zobj2)
3144 == FAILURE)
3145 {
3146 RETURN_NULL();
3147 }
3148 geom_in_1 = getRelay(zobj1, Geometry_ce_ptr);
3149 geom_in_2 = getRelay(zobj2, Geometry_ce_ptr);
3150
3151 geom_out = GEOSSharedPaths_r(GEOS_G(handle), geom_in_1, geom_in_2);
3152 if ( ! geom_out ) RETURN_NULL(); /* should get an exception first */
3153
3154 /* return_value is a zval */
3155 object_init_ex(return_value, Geometry_ce_ptr);
3156 setRelay(return_value, geom_out);
3157 }
3158 #endif
3159
3160 /**
3161 * GEOSGeometry::delaunayTriangulation([<tolerance>], [<onlyEdges>])
3162 *
3163 * 'tolerance'
3164 * Type: double
3165 * snapping tolerance to use for improved robustness
3166 * 'onlyEdges'
3167 * Type: boolean
3168 * if true will return a MULTILINESTRING, otherwise (the default)
3169 * it will return a GEOMETRYCOLLECTION containing triangular POLYGONs.
3170 */
3171 #ifdef HAVE_GEOS_DELAUNAY_TRIANGULATION
PHP_METHOD(Geometry,delaunayTriangulation)3172 PHP_METHOD(Geometry, delaunayTriangulation)
3173 {
3174 GEOSGeometry *this;
3175 GEOSGeometry *ret;
3176 double tolerance = 0.0;
3177 zend_bool edgeonly = 0;
3178
3179 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
3180
3181 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|db",
3182 &tolerance, &edgeonly) == FAILURE) {
3183 RETURN_NULL();
3184 }
3185
3186 ret = GEOSDelaunayTriangulation_r(GEOS_G(handle), this, tolerance, edgeonly ? 1 : 0);
3187 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
3188
3189 /* return_value is a zval */
3190 object_init_ex(return_value, Geometry_ce_ptr);
3191 setRelay(return_value, ret);
3192 }
3193 #endif
3194
3195 /**
3196 * GEOSGeometry::voronoiDiagram([<tolerance>], [<onlyEdges>], [<extent>])
3197 *
3198 * 'tolerance'
3199 * Type: double
3200 * snapping tolerance to use for improved robustness
3201 * 'onlyEdges'
3202 * Type: boolean
3203 * if true will return a MULTILINESTRING, otherwise (the default)
3204 * it will return a GEOMETRYCOLLECTION containing POLYGONs.
3205 * 'extent'
3206 * Type: geometry
3207 * Clip returned diagram by the extent of the given geometry
3208 */
3209 #ifdef HAVE_GEOS_VORONOI_DIAGRAM
PHP_METHOD(Geometry,voronoiDiagram)3210 PHP_METHOD(Geometry, voronoiDiagram)
3211 {
3212 GEOSGeometry *this;
3213 GEOSGeometry *ret;
3214 zval *zobj = 0;
3215 GEOSGeometry *env = 0;
3216 double tolerance = 0.0;
3217 zend_bool edgeonly = 0;
3218
3219 this = (GEOSGeometry*)getRelay(getThis(), Geometry_ce_ptr);
3220
3221 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|dbo",
3222 &tolerance, &edgeonly, &zobj) == FAILURE) {
3223 RETURN_NULL();
3224 }
3225
3226 if ( zobj ) env = getRelay(zobj, Geometry_ce_ptr);
3227 ret = GEOSVoronoiDiagram_r(GEOS_G(handle), this, env, tolerance, edgeonly ? 1 : 0);
3228 if ( ! ret ) RETURN_NULL(); /* should get an exception first */
3229
3230 /* return_value is a zval */
3231 object_init_ex(return_value, Geometry_ce_ptr);
3232 setRelay(return_value, ret);
3233 }
3234 #endif
3235
3236 /**
3237 * bool GEOSRelateMatch(string matrix, string pattern)
3238 */
3239 #ifdef HAVE_GEOS_RELATE_PATTERN_MATCH
PHP_FUNCTION(GEOSRelateMatch)3240 PHP_FUNCTION(GEOSRelateMatch)
3241 {
3242 char* mat = NULL;
3243 char* pat = NULL;
3244 #if PHP_VERSION_ID >= 70000
3245 size_t matlen;
3246 size_t patlen;
3247 #else
3248 int matlen;
3249 int patlen;
3250 #endif
3251 int ret;
3252 zend_bool retBool;
3253
3254 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
3255 &mat, &matlen, &pat, &patlen) == FAILURE)
3256 {
3257 RETURN_NULL();
3258 }
3259
3260 ret = GEOSRelatePatternMatch_r(GEOS_G(handle), mat, pat);
3261 if ( ret == 2 ) RETURN_NULL(); /* should get an exception first */
3262
3263 /* return_value is a zval */
3264 retBool = ret;
3265 RETURN_BOOL(retBool);
3266 }
3267 #endif
3268
3269 /* ------ Initialization / Deinitialization / Meta ------------------ */
3270
3271 /* per-module initialization */
PHP_MINIT_FUNCTION(geos)3272 PHP_MINIT_FUNCTION(geos)
3273 {
3274 zend_class_entry ce;
3275
3276 /* WKTReader */
3277 INIT_CLASS_ENTRY(ce, "GEOSWKTReader", WKTReader_methods);
3278 WKTReader_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
3279 WKTReader_ce_ptr->create_object = WKTReader_create_obj;
3280 memcpy(&WKTReader_object_handlers,
3281 zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3282 WKTReader_object_handlers.clone_obj = NULL;
3283 #if PHP_VERSION_ID >= 70000
3284 WKTReader_object_handlers.offset = XtOffsetOf(Proxy, std);
3285 WKTReader_object_handlers.free_obj = WKTReader_dtor;
3286 #endif
3287
3288 /* WKTWriter */
3289 INIT_CLASS_ENTRY(ce, "GEOSWKTWriter", WKTWriter_methods);
3290 WKTWriter_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
3291 WKTWriter_ce_ptr->create_object = WKTWriter_create_obj;
3292 memcpy(&WKTWriter_object_handlers,
3293 zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3294 WKTWriter_object_handlers.clone_obj = NULL;
3295 #if PHP_VERSION_ID >= 70000
3296 WKTWriter_object_handlers.offset = XtOffsetOf(Proxy, std);
3297 WKTWriter_object_handlers.free_obj = WKTWriter_dtor;
3298 #endif
3299
3300 /* Geometry */
3301 INIT_CLASS_ENTRY(ce, "GEOSGeometry", Geometry_methods);
3302 Geometry_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
3303 Geometry_ce_ptr->create_object = Geometry_create_obj;
3304 memcpy(&Geometry_object_handlers,
3305 zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3306 Geometry_object_handlers.clone_obj = NULL;
3307 /* Geometry serialization */
3308 Geometry_ce_ptr->serialize = Geometry_serialize;
3309 Geometry_ce_ptr->unserialize = Geometry_deserialize;
3310 #if PHP_VERSION_ID >= 70000
3311 Geometry_object_handlers.offset = XtOffsetOf(Proxy, std);
3312 Geometry_object_handlers.free_obj = Geometry_dtor;
3313 #endif
3314
3315 /* WKBWriter */
3316 INIT_CLASS_ENTRY(ce, "GEOSWKBWriter", WKBWriter_methods);
3317 WKBWriter_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
3318 WKBWriter_ce_ptr->create_object = WKBWriter_create_obj;
3319 memcpy(&WKBWriter_object_handlers,
3320 zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3321 WKBWriter_object_handlers.clone_obj = NULL;
3322 #if PHP_VERSION_ID >= 70000
3323 WKBWriter_object_handlers.offset = XtOffsetOf(Proxy, std);
3324 WKBWriter_object_handlers.free_obj = WKBWriter_dtor;
3325 #endif
3326
3327 /* WKBReader */
3328 INIT_CLASS_ENTRY(ce, "GEOSWKBReader", WKBReader_methods);
3329 WKBReader_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
3330 WKBReader_ce_ptr->create_object = WKBReader_create_obj;
3331 memcpy(&WKBReader_object_handlers,
3332 zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3333 WKBReader_object_handlers.clone_obj = NULL;
3334 #if PHP_VERSION_ID >= 70000
3335 WKBReader_object_handlers.offset = XtOffsetOf(Proxy, std);
3336 WKBReader_object_handlers.free_obj = WKBReader_dtor;
3337 #endif
3338
3339
3340 /* Constants */
3341 REGISTER_LONG_CONSTANT("GEOSBUF_CAP_ROUND", GEOSBUF_CAP_ROUND,
3342 CONST_CS|CONST_PERSISTENT);
3343 REGISTER_LONG_CONSTANT("GEOSBUF_CAP_FLAT", GEOSBUF_CAP_FLAT,
3344 CONST_CS|CONST_PERSISTENT);
3345 REGISTER_LONG_CONSTANT("GEOSBUF_CAP_SQUARE", GEOSBUF_CAP_SQUARE,
3346 CONST_CS|CONST_PERSISTENT);
3347 REGISTER_LONG_CONSTANT("GEOSBUF_JOIN_ROUND", GEOSBUF_JOIN_ROUND,
3348 CONST_CS|CONST_PERSISTENT);
3349 REGISTER_LONG_CONSTANT("GEOSBUF_JOIN_MITRE", GEOSBUF_JOIN_MITRE,
3350 CONST_CS|CONST_PERSISTENT);
3351 REGISTER_LONG_CONSTANT("GEOSBUF_JOIN_BEVEL", GEOSBUF_JOIN_BEVEL,
3352 CONST_CS|CONST_PERSISTENT);
3353
3354 REGISTER_LONG_CONSTANT("GEOS_POINT", GEOS_POINT,
3355 CONST_CS|CONST_PERSISTENT);
3356 REGISTER_LONG_CONSTANT("GEOS_LINESTRING", GEOS_LINESTRING,
3357 CONST_CS|CONST_PERSISTENT);
3358 REGISTER_LONG_CONSTANT("GEOS_LINEARRING", GEOS_LINEARRING,
3359 CONST_CS|CONST_PERSISTENT);
3360 REGISTER_LONG_CONSTANT("GEOS_POLYGON", GEOS_POLYGON,
3361 CONST_CS|CONST_PERSISTENT);
3362 REGISTER_LONG_CONSTANT("GEOS_MULTIPOINT", GEOS_MULTIPOINT,
3363 CONST_CS|CONST_PERSISTENT);
3364 REGISTER_LONG_CONSTANT("GEOS_MULTILINESTRING", GEOS_MULTILINESTRING,
3365 CONST_CS|CONST_PERSISTENT);
3366 REGISTER_LONG_CONSTANT("GEOS_MULTIPOLYGON", GEOS_MULTIPOLYGON,
3367 CONST_CS|CONST_PERSISTENT);
3368 REGISTER_LONG_CONSTANT("GEOS_GEOMETRYCOLLECTION", GEOS_GEOMETRYCOLLECTION,
3369 CONST_CS|CONST_PERSISTENT);
3370
3371 REGISTER_LONG_CONSTANT("GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE",
3372 GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE,
3373 CONST_CS|CONST_PERSISTENT);
3374
3375 # ifdef HAVE_GEOS_PREC_NO_TOPO
3376 REGISTER_LONG_CONSTANT("GEOS_PREC_NO_TOPO", GEOS_PREC_NO_TOPO,
3377 CONST_CS|CONST_PERSISTENT);
3378 # endif
3379
3380 # ifdef HAVE_GEOS_PREC_KEEP_COLLAPSED
3381 REGISTER_LONG_CONSTANT("GEOS_PREC_KEEP_COLLAPSED", GEOS_PREC_KEEP_COLLAPSED,
3382 CONST_CS|CONST_PERSISTENT);
3383 # endif
3384
3385 REGISTER_LONG_CONSTANT("GEOSRELATE_BNR_MOD2", GEOSRELATE_BNR_MOD2,
3386 CONST_CS|CONST_PERSISTENT);
3387 REGISTER_LONG_CONSTANT("GEOSRELATE_BNR_OGC", GEOSRELATE_BNR_OGC,
3388 CONST_CS|CONST_PERSISTENT);
3389 REGISTER_LONG_CONSTANT("GEOSRELATE_BNR_ENDPOINT", GEOSRELATE_BNR_ENDPOINT,
3390 CONST_CS|CONST_PERSISTENT);
3391 REGISTER_LONG_CONSTANT("GEOSRELATE_BNR_MULTIVALENT_ENDPOINT",
3392 GEOSRELATE_BNR_MULTIVALENT_ENDPOINT,
3393 CONST_CS|CONST_PERSISTENT);
3394 REGISTER_LONG_CONSTANT("GEOSRELATE_BNR_MONOVALENT_ENDPOINT",
3395 GEOSRELATE_BNR_MONOVALENT_ENDPOINT,
3396 CONST_CS|CONST_PERSISTENT);
3397
3398 return SUCCESS;
3399 }
3400
3401 /* per-module shutdown */
PHP_MSHUTDOWN_FUNCTION(geos)3402 PHP_MSHUTDOWN_FUNCTION(geos)
3403 {
3404 delGeometrySerializer();
3405 delGeometryDeserializer();
3406 return SUCCESS;
3407 }
3408
3409 /* per-request initialization */
PHP_RINIT_FUNCTION(geos)3410 PHP_RINIT_FUNCTION(geos)
3411 {
3412 GEOS_G(handle) = initGEOS_r(noticeHandler, errorHandler);
3413 return SUCCESS;
3414 }
3415
3416 /* pre-request destruction */
PHP_RSHUTDOWN_FUNCTION(geos)3417 PHP_RSHUTDOWN_FUNCTION(geos)
3418 {
3419 finishGEOS_r(GEOS_G(handle));
3420 return SUCCESS;
3421 }
3422
3423 /* global initialization */
PHP_GINIT_FUNCTION(geos)3424 PHP_GINIT_FUNCTION(geos)
3425 {
3426 geos_globals->handle = NULL;
3427 }
3428
3429 /* module info */
PHP_MINFO_FUNCTION(geos)3430 PHP_MINFO_FUNCTION(geos)
3431 {
3432 php_info_print_table_start();
3433 php_info_print_table_row(2,
3434 "GEOS - Geometry Engine Open Source", "enabled");
3435 php_info_print_table_row(2,
3436 "Version", PHP_GEOS_VERSION);
3437 php_info_print_table_row(2,
3438 "GEOS Version", GEOSversion());
3439 php_info_print_table_end();
3440 }
3441