PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
liblwgeom/lwgeom_sfcgal.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://postgis.net
5 *
6 * PostGIS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * PostGIS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * Copyright 2012-2013 Oslandia <infos@oslandia.com>
22 *
23 **********************************************************************/
24
25#include "lwgeom_sfcgal.h"
26
27static int SFCGAL_type_to_lwgeom_type(sfcgal_geometry_type_t type);
28static POINTARRAY *ptarray_from_SFCGAL(const sfcgal_geometry_t *geom, int force3D);
29static sfcgal_geometry_t *ptarray_to_SFCGAL(const POINTARRAY *pa, int type);
30
31/* Return SFCGAL version string */
32const char *
34{
35 const char *version = sfcgal_version();
36 return version;
37}
38
39/*
40 * Mapping between SFCGAL and PostGIS types
41 *
42 * Throw an error if type is unsupported
43 */
44static int
45SFCGAL_type_to_lwgeom_type(sfcgal_geometry_type_t type)
46{
47 switch (type)
48 {
49 case SFCGAL_TYPE_POINT:
50 return POINTTYPE;
51
52 case SFCGAL_TYPE_LINESTRING:
53 return LINETYPE;
54
55 case SFCGAL_TYPE_POLYGON:
56 return POLYGONTYPE;
57
58 case SFCGAL_TYPE_MULTIPOINT:
59 return MULTIPOINTTYPE;
60
61 case SFCGAL_TYPE_MULTILINESTRING:
62 return MULTILINETYPE;
63
64 case SFCGAL_TYPE_MULTIPOLYGON:
65 return MULTIPOLYGONTYPE;
66
67 case SFCGAL_TYPE_MULTISOLID:
68 return COLLECTIONTYPE; /* Nota: PolyhedralSurface closed inside
69 aim is to use true solid type as soon
70 as available in OGC SFS */
71
72 case SFCGAL_TYPE_GEOMETRYCOLLECTION:
73 return COLLECTIONTYPE;
74
75#if 0
76 case SFCGAL_TYPE_CIRCULARSTRING:
77 return CIRCSTRINGTYPE;
78
79 case SFCGAL_TYPE_COMPOUNDCURVE:
80 return COMPOUNDTYPE;
81
82 case SFCGAL_TYPE_CURVEPOLYGON:
83 return CURVEPOLYTYPE;
84
85 case SFCGAL_TYPE_MULTICURVE:
86 return MULTICURVETYPE;
87
88 case SFCGAL_TYPE_MULTISURFACE:
89 return MULTISURFACETYPE;
90#endif
91
92 case SFCGAL_TYPE_POLYHEDRALSURFACE:
94
95 case SFCGAL_TYPE_TRIANGULATEDSURFACE:
96 return TINTYPE;
97
98 case SFCGAL_TYPE_TRIANGLE:
99 return TRIANGLETYPE;
100
101 default:
102 lwerror("SFCGAL_type_to_lwgeom_type: Unknown Type");
103 return 0;
104 }
105}
106
107/*
108 * Return a PostGIS pointarray from a simple SFCGAL geometry:
109 * POINT, LINESTRING or TRIANGLE
110 *
111 * Throw an error on others types
112 */
113static POINTARRAY *
114ptarray_from_SFCGAL(const sfcgal_geometry_t *geom, int want3d)
115{
116 POINT4D point;
117 uint32_t i, npoints;
118 POINTARRAY *pa = NULL;
119
120 assert(geom);
121
122 switch (sfcgal_geometry_type_id(geom))
123 {
124 case SFCGAL_TYPE_POINT:
125 {
126 pa = ptarray_construct(want3d, 0, 1);
127 point.x = sfcgal_point_x(geom);
128 point.y = sfcgal_point_y(geom);
129
130 if (sfcgal_geometry_is_3d(geom))
131 point.z = sfcgal_point_z(geom);
132 else if (want3d)
133 point.z = 0.0;
134
135 ptarray_set_point4d(pa, 0, &point);
136 }
137 break;
138
139 case SFCGAL_TYPE_LINESTRING:
140 {
141 npoints = sfcgal_linestring_num_points(geom);
142 pa = ptarray_construct(want3d, 0, npoints);
143
144 for (i = 0; i < npoints; i++)
145 {
146 const sfcgal_geometry_t *pt = sfcgal_linestring_point_n(geom, i);
147 point.x = sfcgal_point_x(pt);
148 point.y = sfcgal_point_y(pt);
149
150 if (sfcgal_geometry_is_3d(geom))
151 point.z = sfcgal_point_z(pt);
152 else if (want3d)
153 point.z = 0.0;
154
155 ptarray_set_point4d(pa, i, &point);
156 }
157 }
158 break;
159
160 case SFCGAL_TYPE_TRIANGLE:
161 {
162 pa = ptarray_construct(want3d, 0, 4);
163
164 for (i = 0; i < 4; i++)
165 {
166 const sfcgal_geometry_t *pt = sfcgal_triangle_vertex(geom, (i % 3));
167 point.x = sfcgal_point_x(pt);
168 point.y = sfcgal_point_y(pt);
169
170 if (sfcgal_geometry_is_3d(geom))
171 point.z = sfcgal_point_z(pt);
172 else if (want3d)
173 point.z = 0.0;
174
175 ptarray_set_point4d(pa, i, &point);
176 }
177 }
178 break;
179
180 /* Other types should not be called directly ... */
181 default:
182 lwerror("ptarray_from_SFCGAL: Unknown Type");
183 break;
184 }
185 return pa;
186}
187
188/*
189 * Convert a PostGIS pointarray to SFCGAL structure
190 *
191 * Used for simple LWGEOM geometry POINT, LINESTRING, TRIANGLE
192 * and POLYGON rings
193 */
194static sfcgal_geometry_t *
195ptarray_to_SFCGAL(const POINTARRAY *pa, int type)
196{
197 POINT3DZ point;
198 int is_3d;
199 uint32_t i;
200
201 assert(pa);
202
203 is_3d = FLAGS_GET_Z(pa->flags) != 0;
204
205 switch (type)
206 {
207 case POINTTYPE:
208 {
209 getPoint3dz_p(pa, 0, &point);
210 if (is_3d)
211 return sfcgal_point_create_from_xyz(point.x, point.y, point.z);
212 else
213 return sfcgal_point_create_from_xy(point.x, point.y);
214 }
215 break;
216
217 case LINETYPE:
218 {
219 sfcgal_geometry_t *line = sfcgal_linestring_create();
220
221 for (i = 0; i < pa->npoints; i++)
222 {
223 getPoint3dz_p(pa, i, &point);
224 if (is_3d)
225 {
226 sfcgal_linestring_add_point(line,
227 sfcgal_point_create_from_xyz(point.x, point.y, point.z));
228 }
229 else
230 {
231 sfcgal_linestring_add_point(line, sfcgal_point_create_from_xy(point.x, point.y));
232 }
233 }
234
235 return line;
236 }
237 break;
238
239 case TRIANGLETYPE:
240 {
241 sfcgal_geometry_t *triangle = sfcgal_triangle_create();
242
243 getPoint3dz_p(pa, 0, &point);
244 if (is_3d)
245 sfcgal_triangle_set_vertex_from_xyz(triangle, 0, point.x, point.y, point.z);
246 else
247 sfcgal_triangle_set_vertex_from_xy(triangle, 0, point.x, point.y);
248
249 getPoint3dz_p(pa, 1, &point);
250 if (is_3d)
251 sfcgal_triangle_set_vertex_from_xyz(triangle, 1, point.x, point.y, point.z);
252 else
253 sfcgal_triangle_set_vertex_from_xy(triangle, 1, point.x, point.y);
254
255 getPoint3dz_p(pa, 2, &point);
256 if (is_3d)
257 sfcgal_triangle_set_vertex_from_xyz(triangle, 2, point.x, point.y, point.z);
258 else
259 sfcgal_triangle_set_vertex_from_xy(triangle, 2, point.x, point.y);
260
261 return triangle;
262 }
263 break;
264
265 /* Other SFCGAL types should not be called directly ... */
266 default:
267 lwerror("ptarray_from_SFCGAL: Unknown Type");
268 return NULL;
269 }
270}
271
272/*
273 * Convert a SFCGAL structure to PostGIS LWGEOM
274 *
275 * Throws an error on unsupported type
276 */
277LWGEOM *
278SFCGAL2LWGEOM(const sfcgal_geometry_t *geom, int force3D, int32_t srid)
279{
280 uint32_t ngeoms, nshells, nsolids;
281 uint32_t i, j, k;
282 int want3d;
283
284 assert(geom);
285
286 want3d = force3D || sfcgal_geometry_is_3d(geom);
287
288 switch (sfcgal_geometry_type_id(geom))
289 {
290 case SFCGAL_TYPE_POINT:
291 {
292 if (sfcgal_geometry_is_empty(geom))
293 return (LWGEOM *)lwpoint_construct_empty(srid, want3d, 0);
294
295 POINTARRAY *pa = ptarray_from_SFCGAL(geom, want3d);
296 return (LWGEOM *)lwpoint_construct(srid, NULL, pa);
297 }
298
299 case SFCGAL_TYPE_LINESTRING:
300 {
301 if (sfcgal_geometry_is_empty(geom))
302 return (LWGEOM *)lwline_construct_empty(srid, want3d, 0);
303
304 POINTARRAY *pa = ptarray_from_SFCGAL(geom, want3d);
305 return (LWGEOM *)lwline_construct(srid, NULL, pa);
306 }
307
308 case SFCGAL_TYPE_TRIANGLE:
309 {
310 if (sfcgal_geometry_is_empty(geom))
311 return (LWGEOM *)lwtriangle_construct_empty(srid, want3d, 0);
312
313 POINTARRAY *pa = ptarray_from_SFCGAL(geom, want3d);
314 return (LWGEOM *)lwtriangle_construct(srid, NULL, pa);
315 }
316
317 case SFCGAL_TYPE_POLYGON:
318 {
319 if (sfcgal_geometry_is_empty(geom))
320 return (LWGEOM *)lwpoly_construct_empty(srid, want3d, 0);
321
322 uint32_t nrings = sfcgal_polygon_num_interior_rings(geom) + 1;
323 POINTARRAY **pa = (POINTARRAY **)lwalloc(sizeof(POINTARRAY *) * nrings);
324
325 pa[0] = ptarray_from_SFCGAL(sfcgal_polygon_exterior_ring(geom), want3d);
326 for (i = 1; i < nrings; i++)
327 pa[i] = ptarray_from_SFCGAL(sfcgal_polygon_interior_ring_n(geom, i - 1), want3d);
328
329 return (LWGEOM *)lwpoly_construct(srid, NULL, nrings, pa);
330 }
331
332 case SFCGAL_TYPE_MULTIPOINT:
333 case SFCGAL_TYPE_MULTILINESTRING:
334 case SFCGAL_TYPE_MULTIPOLYGON:
335 case SFCGAL_TYPE_MULTISOLID:
336 case SFCGAL_TYPE_GEOMETRYCOLLECTION:
337 {
338 ngeoms = sfcgal_geometry_collection_num_geometries(geom);
339 LWGEOM **geoms = NULL;
340 if (ngeoms)
341 {
342 nsolids = 0;
343 geoms = (LWGEOM **)lwalloc(sizeof(LWGEOM *) * ngeoms);
344 for (i = 0; i < ngeoms; i++)
345 {
346 const sfcgal_geometry_t *g = sfcgal_geometry_collection_geometry_n(geom, i);
347 geoms[i] = SFCGAL2LWGEOM(g, 0, srid);
348 if (FLAGS_GET_SOLID(geoms[i]->flags))
349 ++nsolids;
350 }
351 geoms = (LWGEOM **)lwrealloc(geoms, sizeof(LWGEOM *) * ngeoms);
352 }
354 SFCGAL_type_to_lwgeom_type(sfcgal_geometry_type_id(geom)), srid, NULL, ngeoms, geoms);
355 if (ngeoms)
356 {
357 if (ngeoms == nsolids)
358 FLAGS_SET_SOLID(rgeom->flags, 1);
359 else if (nsolids)
360 lwnotice(
361 "SFCGAL2LWGEOM: SOLID in heterogeneous collection will be treated as a POLYHEDRALSURFACETYPE");
362 }
363 return rgeom;
364 }
365
366#if 0
367 case SFCGAL_TYPE_CIRCULARSTRING:
368 case SFCGAL_TYPE_COMPOUNDCURVE:
369 case SFCGAL_TYPE_CURVEPOLYGON:
370 case SFCGAL_TYPE_MULTICURVE:
371 case SFCGAL_TYPE_MULTISURFACE:
372 case SFCGAL_TYPE_CURVE:
373 case SFCGAL_TYPE_SURFACE:
374
375 /* TODO curve types handling */
376#endif
377
378 case SFCGAL_TYPE_POLYHEDRALSURFACE:
379 {
380 ngeoms = sfcgal_polyhedral_surface_num_polygons(geom);
381
382 LWGEOM **geoms = NULL;
383 if (ngeoms)
384 {
385 geoms = (LWGEOM **)lwalloc(sizeof(LWGEOM *) * ngeoms);
386 for (i = 0; i < ngeoms; i++)
387 {
388 const sfcgal_geometry_t *g = sfcgal_polyhedral_surface_polygon_n(geom, i);
389 geoms[i] = SFCGAL2LWGEOM(g, 0, srid);
390 }
391 }
392 return (LWGEOM *)lwcollection_construct(POLYHEDRALSURFACETYPE, srid, NULL, ngeoms, geoms);
393 }
394
395 /* Solid is map as a closed PolyhedralSurface (for now) */
396 case SFCGAL_TYPE_SOLID:
397 {
398 nshells = sfcgal_solid_num_shells(geom);
399
400 for (ngeoms = 0, i = 0; i < nshells; i++)
401 ngeoms += sfcgal_polyhedral_surface_num_polygons(sfcgal_solid_shell_n(geom, i));
402
403 LWGEOM **geoms = 0;
404 if (ngeoms)
405 {
406 geoms = (LWGEOM **)lwalloc(sizeof(LWGEOM *) * ngeoms);
407 for (i = 0, k = 0; i < nshells; i++)
408 {
409 const sfcgal_geometry_t *shell = sfcgal_solid_shell_n(geom, i);
410 ngeoms = sfcgal_polyhedral_surface_num_polygons(shell);
411
412 for (j = 0; j < ngeoms; j++)
413 {
414 const sfcgal_geometry_t *g = sfcgal_polyhedral_surface_polygon_n(shell, j);
415 geoms[k] = SFCGAL2LWGEOM(g, 1, srid);
416 k++;
417 }
418 }
419 }
420 LWGEOM *rgeom = (LWGEOM *)lwcollection_construct(POLYHEDRALSURFACETYPE, srid, NULL, ngeoms, geoms);
421 if (ngeoms)
422 FLAGS_SET_SOLID(rgeom->flags, 1);
423 return rgeom;
424 }
425
426 case SFCGAL_TYPE_TRIANGULATEDSURFACE:
427 {
428 ngeoms = sfcgal_triangulated_surface_num_triangles(geom);
429 LWGEOM **geoms = NULL;
430 if (ngeoms)
431 {
432 geoms = (LWGEOM **)lwalloc(sizeof(LWGEOM *) * ngeoms);
433 for (i = 0; i < ngeoms; i++)
434 {
435 const sfcgal_geometry_t *g = sfcgal_triangulated_surface_triangle_n(geom, i);
436 geoms[i] = SFCGAL2LWGEOM(g, 0, srid);
437 }
438 }
439 return (LWGEOM *)lwcollection_construct(TINTYPE, srid, NULL, ngeoms, geoms);
440 }
441
442 default:
443 lwerror("SFCGAL2LWGEOM: Unknown Type");
444 return NULL;
445 }
446}
447
448sfcgal_geometry_t *
450{
451 uint32_t i;
452 sfcgal_geometry_t *ret_geom = NULL;
453
454 assert(geom);
455
456 switch (geom->type)
457 {
458 case POINTTYPE:
459 {
460 const LWPOINT *lwp = (const LWPOINT *)geom;
461 if (lwgeom_is_empty(geom))
462 return sfcgal_point_create();
463
464 return ptarray_to_SFCGAL(lwp->point, POINTTYPE);
465 }
466 break;
467
468 case LINETYPE:
469 {
470 const LWLINE *line = (const LWLINE *)geom;
471 if (lwgeom_is_empty(geom))
472 return sfcgal_linestring_create();
473
474 return ptarray_to_SFCGAL(line->points, LINETYPE);
475 }
476 break;
477
478 case TRIANGLETYPE:
479 {
480 const LWTRIANGLE *triangle = (const LWTRIANGLE *)geom;
481 if (lwgeom_is_empty(geom))
482 return sfcgal_triangle_create();
483 return ptarray_to_SFCGAL(triangle->points, TRIANGLETYPE);
484 }
485 break;
486
487 case POLYGONTYPE:
488 {
489 const LWPOLY *poly = (const LWPOLY *)geom;
490 uint32_t nrings = poly->nrings - 1;
491
492 if (lwgeom_is_empty(geom))
493 return sfcgal_polygon_create();
494
495 sfcgal_geometry_t *exterior_ring = ptarray_to_SFCGAL(poly->rings[0], LINETYPE);
496 ret_geom = sfcgal_polygon_create_from_exterior_ring(exterior_ring);
497
498 for (i = 0; i < nrings; i++)
499 {
500 sfcgal_geometry_t *ring = ptarray_to_SFCGAL(poly->rings[i + 1], LINETYPE);
501 sfcgal_polygon_add_interior_ring(ret_geom, ring);
502 }
503 return ret_geom;
504 }
505 break;
506
507 case MULTIPOINTTYPE:
508 case MULTILINETYPE:
509 case MULTIPOLYGONTYPE:
510 case COLLECTIONTYPE:
511 {
512 if (geom->type == MULTIPOINTTYPE)
513 ret_geom = sfcgal_multi_point_create();
514 else if (geom->type == MULTILINETYPE)
515 ret_geom = sfcgal_multi_linestring_create();
516 else if (geom->type == MULTIPOLYGONTYPE)
517 ret_geom = sfcgal_multi_polygon_create();
518 else
519 ret_geom = sfcgal_geometry_collection_create();
520
521 const LWCOLLECTION *lwc = (const LWCOLLECTION *)geom;
522 for (i = 0; i < lwc->ngeoms; i++)
523 {
524 sfcgal_geometry_t *g = LWGEOM2SFCGAL(lwc->geoms[i]);
525 sfcgal_geometry_collection_add_geometry(ret_geom, g);
526 }
527
528 return ret_geom;
529 }
530 break;
531
533 {
534 const LWPSURFACE *lwp = (const LWPSURFACE *)geom;
535 ret_geom = sfcgal_polyhedral_surface_create();
536
537 for (i = 0; i < lwp->ngeoms; i++)
538 {
539 sfcgal_geometry_t *g = LWGEOM2SFCGAL((const LWGEOM *)lwp->geoms[i]);
540 sfcgal_polyhedral_surface_add_polygon(ret_geom, g);
541 }
542 /* We treat polyhedral surface as the only exterior shell,
543 since we can't distinguish exterior from interior shells ... */
544 if (FLAGS_GET_SOLID(lwp->flags))
545 {
546 return sfcgal_solid_create_from_exterior_shell(ret_geom);
547 }
548
549 return ret_geom;
550 }
551 break;
552
553 case TINTYPE:
554 {
555 const LWTIN *lwp = (const LWTIN *)geom;
556 ret_geom = sfcgal_triangulated_surface_create();
557
558 for (i = 0; i < lwp->ngeoms; i++)
559 {
560 sfcgal_geometry_t *g = LWGEOM2SFCGAL((const LWGEOM *)lwp->geoms[i]);
561 sfcgal_triangulated_surface_add_triangle(ret_geom, g);
562 }
563
564 return ret_geom;
565 }
566 break;
567
568 default:
569 lwerror("LWGEOM2SFCGAL: Unknown geometry type !");
570 return NULL;
571 }
572}
573
574/*
575 * No Operation SFCGAL function, used (only) for cunit tests
576 * Take a PostGIS geometry, send it to SFCGAL and return it unchanged (in theory)
577 */
578LWGEOM *
580{
581 sfcgal_geometry_t *converted;
582
583 assert(geom_in);
584
585 converted = LWGEOM2SFCGAL(geom_in);
586 assert(converted);
587
588 LWGEOM *geom_out = SFCGAL2LWGEOM(converted, 0, SRID_UNKNOWN);
589 sfcgal_geometry_delete(converted);
590
591 /* copy SRID (SFCGAL does not store the SRID) */
592 geom_out->srid = geom_in->srid;
593 return geom_out;
594}
static POINTARRAY * ptarray_from_SFCGAL(const sfcgal_geometry_t *geom, int force3D)
static int SFCGAL_type_to_lwgeom_type(sfcgal_geometry_type_t type)
sfcgal_geometry_t * LWGEOM2SFCGAL(const LWGEOM *geom)
const char * lwgeom_sfcgal_version()
LWGEOM * lwgeom_sfcgal_noop(const LWGEOM *geom_in)
static sfcgal_geometry_t * ptarray_to_SFCGAL(const POINTARRAY *pa, int type)
LWGEOM * SFCGAL2LWGEOM(const sfcgal_geometry_t *geom, int force3D, int32_t srid)
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
#define COLLECTIONTYPE
Definition liblwgeom.h:122
#define COMPOUNDTYPE
Definition liblwgeom.h:124
void * lwrealloc(void *mem, size_t size)
Definition lwutil.c:235
#define CURVEPOLYTYPE
Definition liblwgeom.h:125
#define MULTILINETYPE
Definition liblwgeom.h:120
#define MULTISURFACETYPE
Definition liblwgeom.h:127
#define LINETYPE
Definition liblwgeom.h:117
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition lwpoint.c:129
#define MULTIPOINTTYPE
Definition liblwgeom.h:119
LWTRIANGLE * lwtriangle_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwtriangle.c:58
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:116
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:179
void * lwalloc(size_t size)
Definition lwutil.c:227
#define TINTYPE
Definition liblwgeom.h:130
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:121
int getPoint3dz_p(const POINTARRAY *pa, uint32_t n, POINT3DZ *point)
Definition lwgeom_api.c:215
#define POLYGONTYPE
Definition liblwgeom.h:118
#define POLYHEDRALSURFACETYPE
Definition liblwgeom.h:128
#define CIRCSTRINGTYPE
Definition liblwgeom.h:123
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwpoint.c:151
#define FLAGS_GET_SOLID(flags)
Definition liblwgeom.h:184
LWPOLY * lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition lwpoly.c:43
#define MULTICURVETYPE
Definition liblwgeom.h:126
#define TRIANGLETYPE
Definition liblwgeom.h:129
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwpoly.c:161
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:229
LWLINE * lwline_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwline.c:55
#define FLAGS_SET_SOLID(flags, value)
Definition liblwgeom.h:191
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition lwgeom_api.c:376
LWTRIANGLE * lwtriangle_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwtriangle.c:40
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition ptarray.c:51
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition lwutil.c:177
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition lwinline.h:193
uint32_t ngeoms
Definition liblwgeom.h:566
LWGEOM ** geoms
Definition liblwgeom.h:561
uint8_t type
Definition liblwgeom.h:448
int32_t srid
Definition liblwgeom.h:446
lwflags_t flags
Definition liblwgeom.h:447
POINTARRAY * points
Definition liblwgeom.h:469
POINTARRAY * point
Definition liblwgeom.h:457
POINTARRAY ** rings
Definition liblwgeom.h:505
uint32_t nrings
Definition liblwgeom.h:510
lwflags_t flags
Definition liblwgeom.h:633
LWPOLY ** geoms
Definition liblwgeom.h:631
uint32_t ngeoms
Definition liblwgeom.h:636
uint32_t ngeoms
Definition liblwgeom.h:650
LWTRIANGLE ** geoms
Definition liblwgeom.h:645
POINTARRAY * points
Definition liblwgeom.h:481
double z
Definition liblwgeom.h:382
double x
Definition liblwgeom.h:382
double y
Definition liblwgeom.h:382
double x
Definition liblwgeom.h:400
double z
Definition liblwgeom.h:400
double y
Definition liblwgeom.h:400
lwflags_t flags
Definition liblwgeom.h:417
uint32_t npoints
Definition liblwgeom.h:413