-
Notifications
You must be signed in to change notification settings - Fork 363
/
capi_prepared.c
137 lines (116 loc) · 3.71 KB
/
capi_prepared.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* # GEOS C API example 2
*
* Reads one geometry and does a high-performance
* prepared geometry operations to place random
* points inside it.
*/
/* To print to stdout */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
/* Only the CAPI header is required */
#include <geos_c.h>
/*
* GEOS requires two message handlers to return
* error and notice message to the calling program.
*
* typedef void(* GEOSMessageHandler) (const char *fmt,...)
*
* Here we stub out an example that just prints the
* messages to stdout.
*/
static void
geos_message_handler(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprintf (fmt, ap);
va_end(ap);
}
int main()
{
/* Send notice and error messages to our stdout handler */
initGEOS(geos_message_handler, geos_message_handler);
/* One concave polygon */
const char* wkt = "POLYGON ((189 115, 200 170, 130 170, 35 242, 156 215, 210 290, 274 256, 360 190, 267 215, 300 50, 200 60, 189 115))";
/* Read the WKT into geometry objects */
GEOSWKTReader* reader = GEOSWKTReader_create();
GEOSGeometry* geom = GEOSWKTReader_read(reader, wkt);
GEOSWKTReader_destroy(reader);
/* Check for parse success */
if (!geom) {
finishGEOS();
return 1;
}
/* Prepare the geometry */
const GEOSPreparedGeometry* prep_geom = GEOSPrepare(geom);
/* Read bounds of geometry */
double xmin, xmax, ymin, ymax;
GEOSGeom_getXMin(geom, &xmin);
GEOSGeom_getXMax(geom, &xmax);
GEOSGeom_getYMin(geom, &ymin);
GEOSGeom_getYMax(geom, &ymax);
/*
* Set up the point generator
* Generate all the points in the bounding box
* of the input polygon.
*/
const int steps = 10;
double xstep = (xmax - xmin) / steps;
double ystep = (ymax - ymin) / steps;
/* Place to hold points to output */
GEOSGeometry** geoms = (GEOSGeometry**)malloc(steps*steps*sizeof(GEOSGeometry*));
size_t ngeoms = 0;
/*
* Test all the points in the polygon bounding box
* and only keep those that intersect the actual polygon
*/
int i, j;
for (i = 0; i < steps; i++) {
for (j = 0; j < steps; j++) {
/* Make a point in the point grid */
GEOSGeometry* pt = GEOSGeom_createPointFromXY(
xmin + xstep*i,
ymin + ystep*j);
/* Check if the point and polygon intersect */
if (GEOSPreparedIntersects(prep_geom, pt)) {
/* Save the ones that do */
geoms[ngeoms++] = pt;
}
else {
/* Clean up the ones that don't */
GEOSGeom_destroy(pt);
}
}
}
/* Put the successful geoms inside a geometry for WKT output */
GEOSGeometry* result = GEOSGeom_createCollection(GEOS_MULTIPOINT, geoms, ngeoms);
/*
* The GEOSGeom_createCollection() only takes ownership of the
* geometries, not the array container, so we can free the container
* now
*/
free(geoms);
/* Convert result to WKT */
GEOSWKTWriter* writer = GEOSWKTWriter_create();
/* Trim trailing zeros off output */
GEOSWKTWriter_setTrim(writer, 1);
GEOSWKTWriter_setRoundingPrecision(writer, 3);
char* wkt_result = GEOSWKTWriter_write(writer, result);
GEOSWKTWriter_destroy(writer);
/* Print answer */
printf("Input Polygon:\n");
printf("%s\n\n", wkt);
printf("Output Points:\n");
printf("%s\n\n", wkt_result);
/* Clean up everything we allocated */
GEOSPreparedGeom_destroy(prep_geom);
GEOSGeom_destroy(geom);
GEOSGeom_destroy(result);
GEOSFree(wkt_result);
/* Clean up the global context */
finishGEOS();
/* Done */
return 0;
}