-
Notifications
You must be signed in to change notification settings - Fork 15
/
tg.h
352 lines (329 loc) · 17.1 KB
/
tg.h
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
// https://github.com/tidwall/tg
//
// Copyright 2023 Joshua J Baker. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.
#ifndef TG_H
#define TG_H
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
/// The base point type used for all geometries.
/// @see PointFuncs
struct tg_point {
double x;
double y;
};
/// The base segment type used in tg_line and tg_ring for joining two vertices.
/// @see SegmentFuncs
struct tg_segment {
struct tg_point a;
struct tg_point b;
};
/// A rectangle defined by a minimum and maximum coordinates.
/// Returned by the tg_geom_rect(), tg_ring_rect(), and other \*_rect()
/// functions for getting a geometry's minumum bounding rectangle.
/// Also used internally for geometry indexing.
/// @see RectFuncs
struct tg_rect {
struct tg_point min;
struct tg_point max;
};
struct tg_line; ///< Find the description in the tg.c file.
struct tg_ring; ///< Find the description in the tg.c file.
struct tg_poly; ///< Find the description in the tg.c file.
struct tg_geom; ///< Find the description in the tg.c file.
/// Geometry types.
///
/// All tg_geom are one of the following underlying types.
///
/// @see tg_geom_typeof()
/// @see tg_geom_type_string()
/// @see GeometryAccessors
enum tg_geom_type {
TG_POINT = 1, ///< Point
TG_LINESTRING = 2, ///< LineString
TG_POLYGON = 3, ///< Polygon
TG_MULTIPOINT = 4, ///< MultiPoint, collection of points
TG_MULTILINESTRING = 5, ///< MultiLineString, collection of linestrings
TG_MULTIPOLYGON = 6, ///< MultiPolygon, collection of polygons
TG_GEOMETRYCOLLECTION = 7, ///< GeometryCollection, collection of geometries
};
/// Geometry indexing options.
///
/// Used for polygons, rings, and lines to make the point-in-polygon and
/// geometry intersection operations fast.
///
/// An index can also be used for efficiently traversing, searching, and
/// performing nearest-neighbor (kNN) queries on the segment using
/// tg_ring_index_*() and tg_ring_nearest() functions.
enum tg_index {
TG_DEFAULT, ///< default is TG_NATURAL or tg_env_set_default_index().
TG_NONE, ///< no indexing available, or disabled.
TG_NATURAL, ///< indexing with natural ring order, for rings/lines
TG_YSTRIPES, ///< indexing using segment striping, rings only
};
/// @defgroup GeometryConstructors Geometry constructors
/// Functions for creating and freeing geometries.
/// @{
struct tg_geom *tg_geom_new_point(struct tg_point point);
struct tg_geom *tg_geom_new_linestring(const struct tg_line *line);
struct tg_geom *tg_geom_new_polygon(const struct tg_poly *poly);
struct tg_geom *tg_geom_new_multipoint(const struct tg_point *points, int npoints);
struct tg_geom *tg_geom_new_multilinestring(const struct tg_line *const lines[], int nlines);
struct tg_geom *tg_geom_new_multipolygon(const struct tg_poly *const polys[], int npolys);
struct tg_geom *tg_geom_new_geometrycollection(const struct tg_geom *const geoms[], int ngeoms);
struct tg_geom *tg_geom_new_error(const char *errmsg);
struct tg_geom *tg_geom_clone(const struct tg_geom *geom);
struct tg_geom *tg_geom_copy(const struct tg_geom *geom);
void tg_geom_free(struct tg_geom *geom);
/// @}
/// @defgroup GeometryAccessors Geometry accessors
/// Functions for accessing various information about geometries, such as
/// getting the geometry type or extracting underlying components or
/// coordinates.
/// @{
enum tg_geom_type tg_geom_typeof(const struct tg_geom *geom);
const char *tg_geom_type_string(enum tg_geom_type type);
struct tg_rect tg_geom_rect(const struct tg_geom *geom);
bool tg_geom_is_feature(const struct tg_geom *geom);
bool tg_geom_is_featurecollection(const struct tg_geom *geom);
struct tg_point tg_geom_point(const struct tg_geom *geom);
const struct tg_line *tg_geom_line(const struct tg_geom *geom);
const struct tg_poly *tg_geom_poly(const struct tg_geom *geom);
int tg_geom_num_points(const struct tg_geom *geom);
struct tg_point tg_geom_point_at(const struct tg_geom *geom, int index);
int tg_geom_num_lines(const struct tg_geom *geom);
const struct tg_line *tg_geom_line_at(const struct tg_geom *geom, int index);
int tg_geom_num_polys(const struct tg_geom *geom);
const struct tg_poly *tg_geom_poly_at(const struct tg_geom *geom, int index);
int tg_geom_num_geometries(const struct tg_geom *geom);
const struct tg_geom *tg_geom_geometry_at(const struct tg_geom *geom, int index);
const char *tg_geom_extra_json(const struct tg_geom *geom);
bool tg_geom_is_empty(const struct tg_geom *geom);
int tg_geom_dims(const struct tg_geom *geom);
bool tg_geom_has_z(const struct tg_geom *geom);
bool tg_geom_has_m(const struct tg_geom *geom);
double tg_geom_z(const struct tg_geom *geom);
double tg_geom_m(const struct tg_geom *geom);
const double *tg_geom_extra_coords(const struct tg_geom *geom);
int tg_geom_num_extra_coords(const struct tg_geom *geom);
size_t tg_geom_memsize(const struct tg_geom *geom);
void tg_geom_search(const struct tg_geom *geom, struct tg_rect rect,
bool (*iter)(const struct tg_geom *geom, int index, void *udata),
void *udata);
/// @}
/// @defgroup GeometryPredicates Geometry predicates
/// Functions for testing the spatial relations of two geometries.
/// @{
bool tg_geom_equals(const struct tg_geom *a, const struct tg_geom *b);
bool tg_geom_intersects(const struct tg_geom *a, const struct tg_geom *b);
bool tg_geom_disjoint(const struct tg_geom *a, const struct tg_geom *b);
bool tg_geom_contains(const struct tg_geom *a, const struct tg_geom *b);
bool tg_geom_within(const struct tg_geom *a, const struct tg_geom *b);
bool tg_geom_covers(const struct tg_geom *a, const struct tg_geom *b);
bool tg_geom_coveredby(const struct tg_geom *a, const struct tg_geom *b);
bool tg_geom_touches(const struct tg_geom *a, const struct tg_geom *b);
bool tg_geom_intersects_rect(const struct tg_geom *a, struct tg_rect b);
bool tg_geom_intersects_xy(const struct tg_geom *a, double x, double y);
/// @}
/// @defgroup GeometryParsing Geometry parsing
/// Functions for parsing geometries from external data representations.
/// It's recommended to use tg_geom_error() after parsing to check for errors.
/// @{
struct tg_geom *tg_parse_geojson(const char *geojson);
struct tg_geom *tg_parse_geojsonn(const char *geojson, size_t len);
struct tg_geom *tg_parse_geojson_ix(const char *geojson, enum tg_index ix);
struct tg_geom *tg_parse_geojsonn_ix(const char *geojson, size_t len, enum tg_index ix);
struct tg_geom *tg_parse_wkt(const char *wkt);
struct tg_geom *tg_parse_wktn(const char *wkt, size_t len);
struct tg_geom *tg_parse_wkt_ix(const char *wkt, enum tg_index ix);
struct tg_geom *tg_parse_wktn_ix(const char *wkt, size_t len, enum tg_index ix);
struct tg_geom *tg_parse_wkb(const uint8_t *wkb, size_t len);
struct tg_geom *tg_parse_wkb_ix(const uint8_t *wkb, size_t len, enum tg_index ix);
struct tg_geom *tg_parse_hex(const char *hex);
struct tg_geom *tg_parse_hexn(const char *hex, size_t len);
struct tg_geom *tg_parse_hex_ix(const char *hex, enum tg_index ix);
struct tg_geom *tg_parse_hexn_ix(const char *hex, size_t len, enum tg_index ix);
struct tg_geom *tg_parse(const void *data, size_t len);
struct tg_geom *tg_parse_ix(const void *data, size_t len, enum tg_index ix);
const char *tg_geom_error(const struct tg_geom *geom);
/// @}
/// @defgroup GeometryWriting Geometry writing
/// Functions for writing geometries as external data representations.
/// @{
size_t tg_geom_geojson(const struct tg_geom *geom, char *dst, size_t n);
size_t tg_geom_wkt(const struct tg_geom *geom, char *dst, size_t n);
size_t tg_geom_wkb(const struct tg_geom *geom, uint8_t *dst, size_t n);
size_t tg_geom_hex(const struct tg_geom *geom, char *dst, size_t n);
/// @}
/// @defgroup GeometryConstructorsEx Geometry with alternative dimensions
/// Functions for working with geometries that have more than two dimensions or
/// are empty. The extra dimensional coordinates contained within these
/// geometries are only carried along and serve no other purpose than to be
/// available for when it's desired to export to an output representation such
/// as GeoJSON, WKT, or WKB.
/// @{
struct tg_geom *tg_geom_new_point_z(struct tg_point point, double z);
struct tg_geom *tg_geom_new_point_m(struct tg_point point, double m);
struct tg_geom *tg_geom_new_point_zm(struct tg_point point, double z, double m);
struct tg_geom *tg_geom_new_point_empty(void);
struct tg_geom *tg_geom_new_linestring_z(const struct tg_line *line, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_linestring_m(const struct tg_line *line, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_linestring_zm(const struct tg_line *line, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_linestring_empty(void);
struct tg_geom *tg_geom_new_polygon_z(const struct tg_poly *poly, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_polygon_m(const struct tg_poly *poly, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_polygon_zm(const struct tg_poly *poly, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_polygon_empty(void);
struct tg_geom *tg_geom_new_multipoint_z(const struct tg_point *points, int npoints, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multipoint_m(const struct tg_point *points, int npoints, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multipoint_zm(const struct tg_point *points, int npoints, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multipoint_empty(void);
struct tg_geom *tg_geom_new_multilinestring_z(const struct tg_line *const lines[], int nlines, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multilinestring_m(const struct tg_line *const lines[], int nlines, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multilinestring_zm(const struct tg_line *const lines[], int nlines, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multilinestring_empty(void);
struct tg_geom *tg_geom_new_multipolygon_z(const struct tg_poly *const polys[], int npolys, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multipolygon_m(const struct tg_poly *const polys[], int npolys, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multipolygon_zm(const struct tg_poly *const polys[], int npolys, const double *extra_coords, int ncoords);
struct tg_geom *tg_geom_new_multipolygon_empty(void);
struct tg_geom *tg_geom_new_geometrycollection_empty(void);
/// @}
/// @defgroup PointFuncs Point functions
/// Functions for working directly with the tg_point type.
/// @{
struct tg_rect tg_point_rect(struct tg_point point);
bool tg_point_intersects_rect(struct tg_point a, struct tg_rect b);
/// @}
/// @defgroup SegmentFuncs Segment functions
/// Functions for working directly with the tg_segment type.
/// @{
struct tg_rect tg_segment_rect(struct tg_segment s);
bool tg_segment_intersects_segment(struct tg_segment a, struct tg_segment b);
/// @}
/// @defgroup RectFuncs Rectangle functions
/// Functions for working directly with the tg_rect type.
/// @{
struct tg_rect tg_rect_expand(struct tg_rect rect, struct tg_rect other);
struct tg_rect tg_rect_expand_point(struct tg_rect rect, struct tg_point point);
struct tg_point tg_rect_center(struct tg_rect rect);
bool tg_rect_intersects_rect(struct tg_rect a, struct tg_rect b);
bool tg_rect_intersects_point(struct tg_rect a, struct tg_point b);
/// @}
/// @defgroup RingFuncs Ring functions
/// Functions for working directly with the tg_ring type.
///
/// There are no direct spatial predicates for tg_ring.
/// If you want to perform operations like "intersects" or "covers" then you
/// must upcast the ring to a tg_geom, like such:
///
/// ```
/// tg_geom_intersects((struct tg_geom*)ring, geom);
/// ```
/// @{
struct tg_ring *tg_ring_new(const struct tg_point *points, int npoints);
struct tg_ring *tg_ring_new_ix(const struct tg_point *points, int npoints, enum tg_index ix);
void tg_ring_free(struct tg_ring *ring);
struct tg_ring *tg_ring_clone(const struct tg_ring *ring);
struct tg_ring *tg_ring_copy(const struct tg_ring *ring);
size_t tg_ring_memsize(const struct tg_ring *ring);
struct tg_rect tg_ring_rect(const struct tg_ring *ring);
int tg_ring_num_points(const struct tg_ring *ring);
struct tg_point tg_ring_point_at(const struct tg_ring *ring, int index);
const struct tg_point *tg_ring_points(const struct tg_ring *ring);
int tg_ring_num_segments(const struct tg_ring *ring);
struct tg_segment tg_ring_segment_at(const struct tg_ring *ring, int index);
bool tg_ring_convex(const struct tg_ring *ring);
bool tg_ring_clockwise(const struct tg_ring *ring);
int tg_ring_index_spread(const struct tg_ring *ring);
int tg_ring_index_num_levels(const struct tg_ring *ring);
int tg_ring_index_level_num_rects(const struct tg_ring *ring, int levelidx);
struct tg_rect tg_ring_index_level_rect(const struct tg_ring *ring, int levelidx, int rectidx);
bool tg_ring_nearest_segment(const struct tg_ring *ring,
double (*rect_dist)(struct tg_rect rect, int *more, void *udata),
double (*seg_dist)(struct tg_segment seg, int *more, void *udata),
bool (*iter)(struct tg_segment seg, double dist, int index, void *udata),
void *udata);
void tg_ring_line_search(const struct tg_ring *a, const struct tg_line *b,
bool (*iter)(struct tg_segment aseg, int aidx, struct tg_segment bseg,
int bidx, void *udata),
void *udata);
void tg_ring_ring_search(const struct tg_ring *a, const struct tg_ring *b,
bool (*iter)(struct tg_segment aseg, int aidx, struct tg_segment bseg,
int bidx, void *udata),
void *udata);
double tg_ring_area(const struct tg_ring *ring);
double tg_ring_perimeter(const struct tg_ring *ring);
/// @}
/// @defgroup LineFuncs Line functions
/// Functions for working directly with the tg_line type.
///
/// There are no direct spatial predicates for tg_line.
/// If you want to perform operations like "intersects" or "covers" then you
/// must upcast the line to a tg_geom, like such:
///
/// ```
/// tg_geom_intersects((struct tg_geom*)line, geom);
/// ```
/// @{
struct tg_line *tg_line_new(const struct tg_point *points, int npoints);
struct tg_line *tg_line_new_ix(const struct tg_point *points, int npoints, enum tg_index ix);
void tg_line_free(struct tg_line *line);
struct tg_line *tg_line_clone(const struct tg_line *line);
struct tg_line *tg_line_copy(const struct tg_line *line);
size_t tg_line_memsize(const struct tg_line *line);
struct tg_rect tg_line_rect(const struct tg_line *line);
int tg_line_num_points(const struct tg_line *line);
const struct tg_point *tg_line_points(const struct tg_line *line);
struct tg_point tg_line_point_at(const struct tg_line *line, int index);
int tg_line_num_segments(const struct tg_line *line);
struct tg_segment tg_line_segment_at(const struct tg_line *line, int index);
bool tg_line_clockwise(const struct tg_line *line);
int tg_line_index_spread(const struct tg_line *line);
int tg_line_index_num_levels(const struct tg_line *line);
int tg_line_index_level_num_rects(const struct tg_line *line, int levelidx);
struct tg_rect tg_line_index_level_rect(const struct tg_line *line, int levelidx, int rectidx);
bool tg_line_nearest_segment(const struct tg_line *line,
double (*rect_dist)(struct tg_rect rect, int *more, void *udata),
double (*seg_dist)(struct tg_segment seg, int *more, void *udata),
bool (*iter)(struct tg_segment seg, double dist, int index, void *udata),
void *udata);
void tg_line_line_search(const struct tg_line *a, const struct tg_line *b,
bool (*iter)(struct tg_segment aseg, int aidx, struct tg_segment bseg,
int bidx, void *udata),
void *udata);
double tg_line_length(const struct tg_line *line);
/// @}
/// @defgroup PolyFuncs Polygon functions
/// Functions for working directly with the tg_poly type.
///
/// There are no direct spatial predicates for tg_poly.
/// If you want to perform operations like "intersects" or "covers" then you
/// must upcast the poly to a tg_geom, like such:
///
/// ```
/// tg_geom_intersects((struct tg_geom*)poly, geom);
/// ```
/// @{
struct tg_poly *tg_poly_new(const struct tg_ring *exterior, const struct tg_ring *const holes[], int nholes);
void tg_poly_free(struct tg_poly *poly);
struct tg_poly *tg_poly_clone(const struct tg_poly *poly);
struct tg_poly *tg_poly_copy(const struct tg_poly *poly);
size_t tg_poly_memsize(const struct tg_poly *poly);
const struct tg_ring *tg_poly_exterior(const struct tg_poly *poly);
int tg_poly_num_holes(const struct tg_poly *poly);
const struct tg_ring *tg_poly_hole_at(const struct tg_poly *poly, int index);
struct tg_rect tg_poly_rect(const struct tg_poly *poly);
bool tg_poly_clockwise(const struct tg_poly *poly);
/// @}
/// @defgroup GlobalFuncs Global environment
/// Functions for optionally setting the behavior of the TG environment.
/// These, if desired, should be called only once at program start up and prior
/// to calling any other tg_*() functions.
/// @{
void tg_env_set_allocator(void *(*malloc)(size_t), void *(*realloc)(void*, size_t), void (*free)(void*));
void tg_env_set_index(enum tg_index ix);
void tg_env_set_index_spread(int spread);
/// @}
#endif // TG_H