More files missing from commit.
[geos.git] / tests / unit / capi / threadtest.c
blobece57856f9beac8cc9f54b26737f2255d176d32f
1 /************************************************************************
3 * $Id: geostest.c 1892 2006-11-02 10:02:59Z strk $
5 * Multithreaded test for C-Wrapper of GEOS library
7 * Copyright (C) 2005 Refractions Research Inc.
9 * This is free software; you can redistribute and/or modify it under
10 * the terms of the GNU Lesser General Public Licence as published
11 * by the Free Software Foundation.
12 * See the COPYING file for more information.
14 * Author: Sandro Santilli <strk@refractions.net>
16 ***********************************************************************/
18 #define _GNU_SOURCE
20 #include <unistd.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <pthread.h>
26 #include "geos_c.h"
28 #define MAXWKTLEN 1047551
30 void
31 usage(char *me)
33 fprintf(stderr, "Usage: %s <wktfile>\n", me);
34 exit(1);
37 void
38 notice1(const char *fmt, ...) {
39 va_list ap;
41 fprintf( stdout, "NOTICE1: ");
43 va_start (ap, fmt);
44 vfprintf( stdout, fmt, ap);
45 va_end(ap);
46 fprintf( stdout, "\n" );
49 void
50 notice2(const char *fmt, ...) {
51 va_list ap;
53 fprintf( stdout, "NOTICE2: ");
55 va_start (ap, fmt);
56 vfprintf( stdout, fmt, ap);
57 va_end(ap);
58 fprintf( stdout, "\n" );
61 void
62 log_and_exit(const char *fmt, ...) {
63 va_list ap;
65 fprintf( stdout, "ERROR: ");
67 va_start (ap, fmt);
68 vfprintf( stdout, fmt, ap);
69 va_end(ap);
70 fprintf( stdout, "\n" );
71 exit(1);
74 void
75 log_and_exit1(const char *fmt, ...) {
76 va_list ap;
78 fprintf( stdout, "ERROR1: ");
80 va_start (ap, fmt);
81 vfprintf( stdout, fmt, ap);
82 va_end(ap);
83 fprintf( stdout, "\n" );
84 pthread_exit(NULL);
87 void
88 log_and_exit2(const char *fmt, ...) {
89 va_list ap;
91 fprintf( stdout, "ERROR2: ");
93 va_start (ap, fmt);
94 vfprintf( stdout, fmt, ap);
95 va_end(ap);
96 fprintf( stdout, "\n" );
97 pthread_exit(NULL);
100 GEOSGeometry*
101 fineGrainedReconstructionTest(const GEOSGeometry* g1,
102 GEOSContextHandle_t handle)
104 GEOSCoordSequence* cs;
105 GEOSGeometry* g2;
106 GEOSGeometry* shell;
107 const GEOSGeometry* gtmp;
108 GEOSGeometry**geoms;
109 unsigned int ngeoms, i;
110 int type;
112 /* Geometry reconstruction from CoordSeq */
113 type = GEOSGeomTypeId_r(handle, g1);
114 switch ( type )
116 case GEOS_POINT:
117 cs = GEOSCoordSeq_clone_r(handle,
118 GEOSGeom_getCoordSeq_r(handle, g1));
119 g2 = GEOSGeom_createPoint_r(handle, cs);
120 return g2;
121 break;
122 case GEOS_LINESTRING:
123 cs = GEOSCoordSeq_clone_r(handle,
124 GEOSGeom_getCoordSeq_r(handle, g1));
125 g2 = GEOSGeom_createLineString_r(handle, cs);
126 return g2;
127 break;
128 case GEOS_LINEARRING:
129 cs = GEOSCoordSeq_clone_r(handle,
130 GEOSGeom_getCoordSeq_r(handle, g1));
131 g2 = GEOSGeom_createLinearRing_r(handle, cs);
132 return g2;
133 break;
134 case GEOS_POLYGON:
135 gtmp = GEOSGetExteriorRing_r(handle, g1);
136 cs = GEOSCoordSeq_clone_r(handle,
137 GEOSGeom_getCoordSeq_r(handle, gtmp));
138 shell = GEOSGeom_createLinearRing_r(handle, cs);
139 ngeoms = GEOSGetNumInteriorRings_r(handle, g1);
140 geoms = malloc(ngeoms*sizeof(GEOSGeometry*));
141 for (i=0; i<ngeoms; i++)
143 gtmp = GEOSGetInteriorRingN_r(handle, g1, i);
144 cs = GEOSCoordSeq_clone_r(handle,
145 GEOSGeom_getCoordSeq_r(handle, gtmp));
146 geoms[i] = GEOSGeom_createLinearRing_r(handle,
147 cs);
149 g2 = GEOSGeom_createPolygon_r(handle, shell, geoms,
150 ngeoms);
151 free(geoms);
152 return g2;
153 break;
154 case GEOS_MULTIPOINT:
155 case GEOS_MULTILINESTRING:
156 case GEOS_MULTIPOLYGON:
157 case GEOS_GEOMETRYCOLLECTION:
158 ngeoms = GEOSGetNumGeometries_r(handle, g1);
159 geoms = malloc(ngeoms*sizeof(GEOSGeometry*));
160 for (i=0; i<ngeoms; i++)
162 gtmp = GEOSGetGeometryN_r(handle, g1, i);
163 geoms[i] = fineGrainedReconstructionTest(gtmp,
164 handle);
166 g2 = GEOSGeom_createCollection_r(handle, type, geoms,
167 ngeoms);
168 free(geoms);
169 return g2;
170 break;
171 default:
172 log_and_exit("Unknown geometry type %d\n", type);
173 return NULL;
177 void
178 printHEX(FILE *where, const unsigned char *bytes, size_t n)
180 static char hex[] = "0123456789ABCDEF";
181 int i;
183 for (i=0; i<n; i++)
185 fprintf(where, "%c%c", hex[bytes[i]>>4], hex[bytes[i]&0x0F]);
190 do_all(char *inputfile, GEOSContextHandle_t handle)
192 GEOSGeometry* g1;
193 GEOSGeometry* g2;
194 GEOSGeometry* g3;
195 GEOSGeometry* g4;
196 const GEOSGeometry **gg;
197 unsigned int npoints, ndims;
198 static char wkt[MAXWKTLEN];
199 FILE *input;
200 char *ptr;
201 unsigned char* uptr;
202 size_t size;
203 double dist, area;
205 input = fopen(inputfile, "r");
206 if ( ! input ) { perror("fopen"); exit(1); }
208 size = fread(wkt, 1, MAXWKTLEN-1, input);
209 fclose(input);
210 if ( ! size ) { perror("fread"); exit(1); }
211 if ( size == MAXWKTLEN-1 ) { perror("WKT input too big!"); exit(1); }
212 wkt[size] = '\0'; /* ensure it is null terminated */
214 /* WKT input */
215 g1 = GEOSGeomFromWKT_r(handle, wkt);
217 /* WKT output */
218 ptr = GEOSGeomToWKT_r(handle, g1);
219 printf("Input (WKT): %s\n", ptr);
220 free(ptr);
222 /* WKB output */
223 uptr = GEOSGeomToWKB_buf_r(handle, g1, &size);
224 printf("Input (WKB): "); printHEX(stdout, uptr, size); putchar('\n');
226 /* WKB input */
227 g2 = GEOSGeomFromWKB_buf_r(handle, uptr, size); free(uptr);
228 if ( ! GEOSEquals_r(handle, g1, g2) ) log_and_exit("Round WKB conversion failed");
229 GEOSGeom_destroy_r(handle, g2);
231 /* Size and dimension */
232 npoints = GEOSGetNumCoordinates_r(handle, g1);
233 ndims = GEOSGeom_getDimensions_r(handle, g1);
234 printf("Geometry coordinates: %dx%d\n", npoints, ndims);
236 /* Geometry fine-grained deconstruction/reconstruction test */
237 g2 = fineGrainedReconstructionTest(g1, handle);
238 if ( ! GEOSEquals_r(handle, g1, g2) )
240 log_and_exit("Reconstruction test failed\n");
242 GEOSGeom_destroy_r(handle, g2);
244 /* Unary predicates */
245 if ( GEOSisEmpty_r(handle, g1) ) printf("isEmpty\n");
246 if ( GEOSisValid_r(handle, g1) ) printf("isValid\n");
247 if ( GEOSisSimple_r(handle, g1) ) printf("isSimple\n");
248 if ( GEOSisRing_r(handle, g1) ) printf("isRing\n");
250 /* Convex Hull */
251 g2 = GEOSConvexHull_r(handle, g1);
252 if ( ! g2 )
254 log_and_exit("GEOSConvexHull() raised an exception");
256 ptr = GEOSGeomToWKT_r(handle, g2);
257 printf("ConvexHull: %s\n", ptr);
258 free(ptr);
260 /* Buffer */
261 GEOSGeom_destroy_r(handle, g1);
262 g1 = GEOSBuffer_r(handle, g2, 100, 30);
263 if ( ! g1 )
265 log_and_exit("GEOSBuffer() raised an exception");
267 ptr = GEOSGeomToWKT_r(handle, g1);
268 printf("Buffer: %s\n", ptr);
269 free(ptr);
272 /* Intersection */
273 g3 = GEOSIntersection_r(handle, g1, g2);
274 if ( ! GEOSEquals_r(handle, g3, g2) )
276 GEOSGeom_destroy_r(handle, g1);
277 GEOSGeom_destroy_r(handle, g2);
278 GEOSGeom_destroy_r(handle, g3);
279 log_and_exit("Intersection(g, Buffer(g)) didn't return g");
281 ptr = GEOSGeomToWKT_r(handle, g3);
282 printf("Intersection: %s\n", ptr);
283 GEOSGeom_destroy_r(handle, g3);
284 free(ptr);
286 /* Difference */
287 g3 = GEOSDifference_r(handle, g1, g2);
288 ptr = GEOSGeomToWKT_r(handle, g3);
289 printf("Difference: %s\n", ptr);
290 GEOSGeom_destroy_r(handle, g3);
291 free(ptr);
293 /* SymDifference */
294 g3 = GEOSSymDifference_r(handle, g1, g2);
295 ptr = GEOSGeomToWKT_r(handle, g3);
296 printf("SymDifference: %s\n", ptr);
297 free(ptr);
299 /* Boundary */
300 g4 = GEOSBoundary_r(handle, g3);
301 ptr = GEOSGeomToWKT_r(handle, g4);
302 printf("Boundary: %s\n", ptr);
303 GEOSGeom_destroy_r(handle, g3);
304 GEOSGeom_destroy_r(handle, g4);
305 free(ptr);
307 /* Union */
308 g3 = GEOSUnion_r(handle, g1, g2);
309 if ( ! GEOSEquals_r(handle, g3, g1) )
311 GEOSGeom_destroy_r(handle, g1);
312 GEOSGeom_destroy_r(handle, g2);
313 GEOSGeom_destroy_r(handle, g3);
314 log_and_exit("Union(g, Buffer(g)) didn't return Buffer(g)");
316 ptr = GEOSGeomToWKT_r(handle, g3);
317 printf("Union: %s\n", ptr);
318 free(ptr);
320 /* PointOnSurcace */
321 g4 = GEOSPointOnSurface_r(handle, g3);
322 ptr = GEOSGeomToWKT_r(handle, g4);
323 printf("PointOnSurface: %s\n", ptr);
324 GEOSGeom_destroy_r(handle, g3);
325 GEOSGeom_destroy_r(handle, g4);
326 free(ptr);
328 /* Centroid */
329 g3 = GEOSGetCentroid_r(handle, g2);
330 ptr = GEOSGeomToWKT_r(handle, g3);
331 printf("Centroid: %s\n", ptr);
332 GEOSGeom_destroy_r(handle, g3);
333 free(ptr);
335 /* Relate (and RelatePattern )*/
336 ptr = GEOSRelate_r(handle, g1, g2);
337 if ( ! GEOSRelatePattern_r(handle, g1, g2, ptr) )
339 GEOSGeom_destroy_r(handle, g1);
340 GEOSGeom_destroy_r(handle, g2);
341 free(ptr);
342 log_and_exit("! RelatePattern(g1, g2, Relate(g1, g2))");
344 printf("Relate: %s\n", ptr);
345 free(ptr);
347 /* Polygonize */
348 gg = (const GEOSGeometry**)malloc(2*sizeof(GEOSGeometry*));
349 gg[0] = g1;
350 gg[1] = g2;
351 g3 = GEOSPolygonize_r(handle, gg, 2);
352 free(gg);
353 if ( ! g3 )
355 log_and_exit("Exception running GEOSPolygonize");
357 ptr = GEOSGeomToWKT_r(handle, g3);
358 GEOSGeom_destroy_r(handle, g3);
359 printf("Polygonize: %s\n", ptr);
360 free(ptr);
362 /* LineMerge */
363 g3 = GEOSLineMerge_r(handle, g1);
364 if ( ! g3 )
366 log_and_exit("Exception running GEOSLineMerge");
368 ptr = GEOSGeomToWKT_r(handle, g3);
369 printf("LineMerge: %s\n", ptr);
370 free(ptr);
371 GEOSGeom_destroy_r(handle, g3);
373 /* Binary predicates */
374 if ( GEOSIntersects_r(handle, g1, g2) ) printf("Intersect\n");
375 if ( GEOSDisjoint_r(handle, g1, g2) ) printf("Disjoint\n");
376 if ( GEOSTouches_r(handle, g1, g2) ) printf("Touches\n");
377 if ( GEOSCrosses_r(handle, g1, g2) ) printf("Crosses\n");
378 if ( GEOSWithin_r(handle, g1, g2) ) printf("Within\n");
379 if ( GEOSContains_r(handle, g1, g2) ) printf("Contains\n");
380 if ( GEOSOverlaps_r(handle, g1, g2) ) printf("Overlaps\n");
382 /* Distance */
383 if ( GEOSDistance_r(handle, g1, g2, &dist) ) printf("Distance: %g\n", dist);
385 /* Area */
386 if ( GEOSArea_r(handle, g1, &area) ) printf("Area 1: %g\n", area);
387 if ( GEOSArea_r(handle, g2, &area) ) printf("Area 2: %g\n", area);
389 GEOSGeom_destroy_r(handle, g2);
391 /* Simplify */
392 g3 = GEOSSimplify_r(handle, g1, 0.5);
393 ptr = GEOSGeomToWKT_r(handle, g3);
394 printf("Simplify: %s\n", ptr);
395 free(ptr);
396 GEOSGeom_destroy_r(handle, g3);
398 /* Topology Preserve Simplify */
399 g3 = GEOSTopologyPreserveSimplify_r(handle, g1, 0.5);
400 ptr = GEOSGeomToWKT_r(handle, g3);
401 printf("Simplify: %s\n", ptr);
402 free(ptr);
403 GEOSGeom_destroy_r(handle, g3);
405 GEOSGeom_destroy_r(handle, g1);
407 return 0;
410 void *threadfunc1( void *arg )
412 GEOSContextHandle_t handle = NULL;
414 handle = initGEOS_r( notice1, log_and_exit1 );
415 printf("GEOS version %s\n", GEOSversion(handle));
416 putc('.', stderr); fflush(stderr);
417 do_all((char*)arg, handle);
418 putc('+', stderr); fflush(stderr);
419 finishGEOS_r(handle);
421 pthread_exit(NULL);
424 void *threadfunc2( void *arg )
426 GEOSContextHandle_t handle = NULL;
428 handle = initGEOS_r( notice2, log_and_exit2 );
429 printf("GEOS version %s\n", GEOSversion(handle));
430 putc('.', stderr); fflush(stderr);
431 do_all((char *)arg, handle);
432 putc('+', stderr); fflush(stderr);
433 finishGEOS_r(handle);
435 pthread_exit(NULL);
439 main(int argc, char **argv)
441 pthread_t thread1, thread2;
443 if ( argc < 2 ) usage(argv[0]);
444 pthread_create( &thread1, NULL, threadfunc1, argv[1] );
445 pthread_create( &thread2, NULL, threadfunc2, argv[1] );
446 pthread_join( thread1, NULL );
447 pthread_join( thread2, NULL );
449 return EXIT_SUCCESS;