PostGIS  2.2.8dev-r@@SVN_REVISION@@
postgis/lwgeom_sfcgal.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * Wrapper around SFCGAL for 3D functions
7  *
8  * Copyright 2012-2013 Oslandia <infos@oslandia.com>
9  *
10  * This is free software; you can redistribute and/or modify it under
11  * the terms of the GNU General Public Licence. See the COPYING file.
12  *
13  **********************************************************************/
14 
15 #include "postgres.h"
16 #include "fmgr.h"
17 #include "../liblwgeom/liblwgeom.h"
18 
19 #include "lwgeom_pg.h"
20 #include "lwgeom_sfcgal.h"
21 #include "../postgis_config.h"
22 
23 
24 Datum postgis_sfcgal_version(PG_FUNCTION_ARGS);
25 
26 Datum sfcgal_from_ewkt(PG_FUNCTION_ARGS);
27 Datum sfcgal_distance(PG_FUNCTION_ARGS);
28 Datum sfcgal_distance3D(PG_FUNCTION_ARGS);
29 Datum sfcgal_area(PG_FUNCTION_ARGS);
30 Datum sfcgal_area3D(PG_FUNCTION_ARGS);
31 Datum sfcgal_intersects(PG_FUNCTION_ARGS);
32 Datum sfcgal_intersects3D(PG_FUNCTION_ARGS);
33 Datum sfcgal_intersection(PG_FUNCTION_ARGS);
34 Datum sfcgal_intersection3D(PG_FUNCTION_ARGS);
35 Datum sfcgal_difference(PG_FUNCTION_ARGS);
36 Datum sfcgal_difference3D(PG_FUNCTION_ARGS);
37 Datum sfcgal_union(PG_FUNCTION_ARGS);
38 Datum sfcgal_union3D(PG_FUNCTION_ARGS);
39 Datum sfcgal_volume(PG_FUNCTION_ARGS);
40 Datum sfcgal_extrude(PG_FUNCTION_ARGS);
41 Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS);
42 Datum sfcgal_approximate_medial_axis(PG_FUNCTION_ARGS);
43 Datum sfcgal_is_planar(PG_FUNCTION_ARGS);
44 Datum sfcgal_orientation(PG_FUNCTION_ARGS);
45 Datum sfcgal_force_lhr(PG_FUNCTION_ARGS);
46 Datum sfcgal_triangulate(PG_FUNCTION_ARGS);
47 Datum sfcgal_tesselate(PG_FUNCTION_ARGS);
48 Datum sfcgal_minkowski_sum(PG_FUNCTION_ARGS);
49 Datum sfcgal_make_solid(PG_FUNCTION_ARGS);
50 Datum sfcgal_is_solid(PG_FUNCTION_ARGS);
51 
52 
54 char* text2cstring(const text *textptr);
55 
56 static int __sfcgal_init = 0;
57 
59 {
60  if ( ! __sfcgal_init ) {
61  sfcgal_init();
62  sfcgal_set_error_handlers((sfcgal_error_handler_t) lwpgnotice, (sfcgal_error_handler_t) lwpgerror);
63  sfcgal_set_alloc_handlers(lwalloc, lwfree);
64  __sfcgal_init = 1;
65  }
66 }
67 
68 
69 /* Conversion from GSERIALIZED* to SFCGAL::Geometry */
70 sfcgal_geometry_t* POSTGIS2SFCGALGeometry(GSERIALIZED *pglwgeom)
71 {
72  sfcgal_geometry_t* g;
73  LWGEOM *lwgeom = lwgeom_from_gserialized(pglwgeom);
74 
75  if (! lwgeom)
76  {
77  lwpgerror("POSTGIS2SFCGALGeometry: Unable to deserialize input");
78  }
79  g = LWGEOM2SFCGAL(lwgeom);
80  lwgeom_free(lwgeom);
81 
82  return g;
83 }
84 
85 
86 /* Conversion from GSERIALIZED* to SFCGAL::PreparedGeometry */
87 sfcgal_prepared_geometry_t* POSTGIS2SFCGALPreparedGeometry(GSERIALIZED *pglwgeom)
88 {
89  sfcgal_geometry_t* g;
90  LWGEOM *lwgeom = lwgeom_from_gserialized(pglwgeom);
91 
92  if (!lwgeom)
93  {
94  lwpgerror("POSTGIS2SFCGALPreparedGeometry: Unable to deserialize input");
95  }
96  g = LWGEOM2SFCGAL(lwgeom);
97 
98  lwgeom_free(lwgeom);
99 
100  return sfcgal_prepared_geometry_create_from_geometry(g, gserialized_get_srid(pglwgeom));
101 }
102 
103 
104 /* Conversion from SFCGAL::Geometry to GSERIALIZED */
105 GSERIALIZED* SFCGALGeometry2POSTGIS(const sfcgal_geometry_t* geom, int force3D, int SRID)
106 {
107  GSERIALIZED *result;
108  LWGEOM* lwgeom = SFCGAL2LWGEOM(geom, force3D, SRID);
109 
110  if (lwgeom_needs_bbox(lwgeom) == LW_TRUE)
111  lwgeom_add_bbox(lwgeom);
112 
113  result = geometry_serialize(lwgeom);
114  lwgeom_free(lwgeom);
115 
116  return result;
117 }
118 
119 
120 /* Conversion from SFCGAL::PreparedGeometry to GSERIALIZED */
121 GSERIALIZED* SFCGALPreparedGeometry2POSTGIS(const sfcgal_prepared_geometry_t* geom, int force3D)
122 {
123  return SFCGALGeometry2POSTGIS(sfcgal_prepared_geometry_geometry(geom),
124  force3D, sfcgal_prepared_geometry_srid(geom));
125 }
126 
127 
128 /* Conversion from EWKT to GSERIALIZED */
130 Datum sfcgal_from_ewkt(PG_FUNCTION_ARGS)
131 {
132  GSERIALIZED* result;
133  sfcgal_prepared_geometry_t* g;
134  text *wkttext = PG_GETARG_TEXT_P(0);
135  char *cstring = text2cstring(wkttext);
136 
138 
139  g = sfcgal_io_read_ewkt( cstring, strlen(cstring) );
140 
141  result = SFCGALPreparedGeometry2POSTGIS( g, 0 );
142  sfcgal_prepared_geometry_delete( g );
143  PG_RETURN_POINTER(result);
144 }
145 
146 
148 Datum sfcgal_area(PG_FUNCTION_ARGS)
149  {
150  GSERIALIZED *input;
151  sfcgal_geometry_t *geom;
152  double result;
153 
155 
156  input = PG_GETARG_GSERIALIZED_P(0);
157  geom = POSTGIS2SFCGALGeometry(input);
158 
159  result = sfcgal_geometry_area(geom);
160  sfcgal_geometry_delete(geom);
161 
162  PG_FREE_IF_COPY(input, 0);
163 
164  PG_RETURN_FLOAT8(result);
165 }
166 
167 
169 Datum sfcgal_area3D(PG_FUNCTION_ARGS)
170  {
171  GSERIALIZED *input;
172  sfcgal_geometry_t *geom;
173  double result;
174 
176 
177  input = PG_GETARG_GSERIALIZED_P(0);
178  geom = POSTGIS2SFCGALGeometry(input);
179 
180  result = sfcgal_geometry_area_3d(geom);
181  sfcgal_geometry_delete(geom);
182 
183  PG_FREE_IF_COPY(input, 0);
184 
185  PG_RETURN_FLOAT8(result);
186 }
187 
188 
190 Datum sfcgal_is_planar(PG_FUNCTION_ARGS)
191 {
192  GSERIALIZED *input;
193  sfcgal_geometry_t *geom;
194  int result;
195 
197 
198  input = PG_GETARG_GSERIALIZED_P(0);
199  geom = POSTGIS2SFCGALGeometry(input);
200 
201  result = sfcgal_geometry_is_planar(geom);
202  sfcgal_geometry_delete(geom);
203 
204  PG_FREE_IF_COPY(input, 0);
205 
206  PG_RETURN_BOOL(result);
207 }
208 
209 
211 Datum sfcgal_orientation(PG_FUNCTION_ARGS)
212 {
213  GSERIALIZED *input;
214  sfcgal_geometry_t *geom;
215  int result;
216 
218 
219  input = PG_GETARG_GSERIALIZED_P(0);
220  geom = POSTGIS2SFCGALGeometry(input);
221 
222  result = sfcgal_geometry_orientation(geom);
223  sfcgal_geometry_delete(geom);
224 
225  PG_FREE_IF_COPY(input, 0);
226 
227  PG_RETURN_INT32(result);
228 }
229 
230 
232 Datum sfcgal_intersects(PG_FUNCTION_ARGS)
233 {
234  GSERIALIZED *input0, *input1;
235  sfcgal_geometry_t *geom0, *geom1;
236  int result;
237 
239 
240  input0 = PG_GETARG_GSERIALIZED_P(0);
241  input1 = PG_GETARG_GSERIALIZED_P(1);
242  geom0 = POSTGIS2SFCGALGeometry(input0);
243  PG_FREE_IF_COPY(input0, 0);
244  geom1 = POSTGIS2SFCGALGeometry(input1);
245  PG_FREE_IF_COPY(input1, 1);
246 
247  result = sfcgal_geometry_intersects(geom0, geom1);
248  sfcgal_geometry_delete(geom0);
249  sfcgal_geometry_delete(geom1);
250 
251  PG_RETURN_BOOL(result);
252 }
253 
254 
256 Datum sfcgal_intersects3D(PG_FUNCTION_ARGS)
257 {
258  GSERIALIZED *input0, *input1;
259  sfcgal_geometry_t *geom0, *geom1;
260  int result;
261 
263 
264  input0 = PG_GETARG_GSERIALIZED_P(0);
265  input1 = PG_GETARG_GSERIALIZED_P(1);
266  geom0 = POSTGIS2SFCGALGeometry(input0);
267  PG_FREE_IF_COPY(input0, 0);
268  geom1 = POSTGIS2SFCGALGeometry(input1);
269  PG_FREE_IF_COPY(input1, 1);
270 
271  result = sfcgal_geometry_intersects_3d(geom0, geom1);
272  sfcgal_geometry_delete(geom0);
273  sfcgal_geometry_delete(geom1);
274 
275  PG_RETURN_BOOL(result);
276 }
277 
278 
280 Datum sfcgal_distance(PG_FUNCTION_ARGS)
281 {
282  GSERIALIZED *input0, *input1;
283  sfcgal_geometry_t *geom0, *geom1;
284  double result;
285 
287 
288  input0 = PG_GETARG_GSERIALIZED_P(0);
289  input1 = PG_GETARG_GSERIALIZED_P(1);
290  geom0 = POSTGIS2SFCGALGeometry(input0);
291  PG_FREE_IF_COPY(input0, 0);
292  geom1 = POSTGIS2SFCGALGeometry(input1);
293  PG_FREE_IF_COPY(input1, 1);
294 
295  result = sfcgal_geometry_distance(geom0, geom1);
296  sfcgal_geometry_delete(geom0);
297  sfcgal_geometry_delete(geom1);
298 
299  PG_RETURN_FLOAT8(result);
300 }
301 
302 
304 Datum sfcgal_distance3D(PG_FUNCTION_ARGS)
305 {
306  GSERIALIZED *input0, *input1;
307  sfcgal_geometry_t *geom0, *geom1;
308  double result;
309 
311 
312  input0 = PG_GETARG_GSERIALIZED_P(0);
313  input1 = PG_GETARG_GSERIALIZED_P(1);
314  geom0 = POSTGIS2SFCGALGeometry(input0);
315  PG_FREE_IF_COPY(input0, 0);
316  geom1 = POSTGIS2SFCGALGeometry(input1);
317  PG_FREE_IF_COPY(input1, 1);
318 
319  result = sfcgal_geometry_distance_3d(geom0, geom1);
320  sfcgal_geometry_delete(geom0);
321  sfcgal_geometry_delete(geom1);
322 
323  PG_RETURN_FLOAT8(result);
324 }
325 
326 
328 Datum sfcgal_tesselate(PG_FUNCTION_ARGS)
329 {
330  GSERIALIZED *input, *output;
331  sfcgal_geometry_t *geom;
332  sfcgal_geometry_t *result;
333  srid_t srid;
334 
336 
337  input = PG_GETARG_GSERIALIZED_P(0);
338  srid = gserialized_get_srid(input);
339  geom = POSTGIS2SFCGALGeometry(input);
340  PG_FREE_IF_COPY(input, 0);
341 
342  result = sfcgal_geometry_tesselate(geom);
343  sfcgal_geometry_delete(geom);
344 
345  output = SFCGALGeometry2POSTGIS(result, 0, srid);
346  sfcgal_geometry_delete(result);
347 
348  PG_RETURN_POINTER(output);
349 }
350 
351 
353 Datum sfcgal_triangulate(PG_FUNCTION_ARGS)
354 {
355  GSERIALIZED *input, *output;
356  sfcgal_geometry_t *geom;
357  sfcgal_geometry_t *result;
358  srid_t srid;
359 
361 
362  input = PG_GETARG_GSERIALIZED_P(0);
363  srid = gserialized_get_srid(input);
364  geom = POSTGIS2SFCGALGeometry(input);
365  PG_FREE_IF_COPY(input, 0);
366 
367  result = sfcgal_geometry_triangulate_2dz(geom);
368  sfcgal_geometry_delete(geom);
369 
370  output = SFCGALGeometry2POSTGIS(result, 0, srid);
371  sfcgal_geometry_delete(result);
372 
373  PG_RETURN_POINTER(output);
374 }
375 
376 
378 Datum sfcgal_force_lhr(PG_FUNCTION_ARGS)
379 {
380  GSERIALIZED *input, *output;
381  sfcgal_geometry_t *geom;
382  sfcgal_geometry_t *result;
383  srid_t srid;
384 
386 
387  input = PG_GETARG_GSERIALIZED_P(0);
388  srid = gserialized_get_srid(input);
389  geom = POSTGIS2SFCGALGeometry(input);
390  PG_FREE_IF_COPY(input, 0);
391 
392  result = sfcgal_geometry_force_lhr(geom);
393  sfcgal_geometry_delete(geom);
394 
395  output = SFCGALGeometry2POSTGIS(result, 0, srid);
396  sfcgal_geometry_delete(result);
397 
398  PG_RETURN_POINTER(output);
399 }
400 
401 
403 Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS)
404 {
405  GSERIALIZED *input, *output;
406  sfcgal_geometry_t *geom;
407  sfcgal_geometry_t *result;
408  srid_t srid;
409 
411 
412  input = PG_GETARG_GSERIALIZED_P(0);
413  srid = gserialized_get_srid(input);
414  geom = POSTGIS2SFCGALGeometry(input);
415  PG_FREE_IF_COPY(input, 0);
416 
417  result = sfcgal_geometry_straight_skeleton(geom);
418  sfcgal_geometry_delete(geom);
419 
420  output = SFCGALGeometry2POSTGIS(result, 0, srid);
421  sfcgal_geometry_delete(result);
422 
423  PG_RETURN_POINTER(output);
424 }
425 
427 Datum sfcgal_approximate_medial_axis(PG_FUNCTION_ARGS)
428 {
429 #if POSTGIS_SFCGAL_VERSION < 12
430  lwpgerror("The SFCGAL version this PostGIS binary "
431  "was compiled against (%d) doesn't support "
432  "'sfcgal_geometry_approximate_medial_axis' function (1.2.0+ required)",
434  PG_RETURN_NULL();
435 #else /* POSTGIS_SFCGAL_VERSION >= 12 */
436  GSERIALIZED *input, *output;
437  sfcgal_geometry_t *geom;
438  sfcgal_geometry_t *result;
439  srid_t srid;
440 
442 
443  input = PG_GETARG_GSERIALIZED_P(0);
444  srid = gserialized_get_srid(input);
445  geom = POSTGIS2SFCGALGeometry(input);
446  PG_FREE_IF_COPY(input, 0);
447 
448  result = sfcgal_geometry_approximate_medial_axis(geom);
449  sfcgal_geometry_delete(geom);
450 
451  output = SFCGALGeometry2POSTGIS(result, 0, srid);
452  sfcgal_geometry_delete(result);
453 
454  PG_RETURN_POINTER(output);
455 #endif /* POSTGIS_SFCGAL_VERSION >= 12 */
456 }
457 
458 
460 Datum sfcgal_intersection(PG_FUNCTION_ARGS)
461 {
462  GSERIALIZED *input0, *input1, *output;
463  sfcgal_geometry_t *geom0, *geom1;
464  sfcgal_geometry_t *result;
465  srid_t srid;
466 
468 
469  input0 = PG_GETARG_GSERIALIZED_P(0);
470  srid = gserialized_get_srid(input0);
471  input1 = PG_GETARG_GSERIALIZED_P(1);
472  geom0 = POSTGIS2SFCGALGeometry(input0);
473  PG_FREE_IF_COPY(input0, 0);
474  geom1 = POSTGIS2SFCGALGeometry(input1);
475  PG_FREE_IF_COPY(input1, 1);
476 
477  result = sfcgal_geometry_intersection(geom0, geom1);
478  sfcgal_geometry_delete(geom0);
479  sfcgal_geometry_delete(geom1);
480 
481  output = SFCGALGeometry2POSTGIS(result, 0, srid);
482  sfcgal_geometry_delete(result);
483 
484  PG_RETURN_POINTER(output);
485 }
486 
487 
489 Datum sfcgal_intersection3D(PG_FUNCTION_ARGS)
490 {
491  GSERIALIZED *input0, *input1, *output;
492  sfcgal_geometry_t *geom0, *geom1;
493  sfcgal_geometry_t *result;
494  srid_t srid;
495 
497 
498  input0 = PG_GETARG_GSERIALIZED_P(0);
499  srid = gserialized_get_srid(input0);
500  input1 = PG_GETARG_GSERIALIZED_P(1);
501  geom0 = POSTGIS2SFCGALGeometry(input0);
502  PG_FREE_IF_COPY(input0, 0);
503  geom1 = POSTGIS2SFCGALGeometry(input1);
504  PG_FREE_IF_COPY(input1, 1);
505 
506  result = sfcgal_geometry_intersection_3d(geom0, geom1);
507  sfcgal_geometry_delete(geom0);
508  sfcgal_geometry_delete(geom1);
509 
510  output = SFCGALGeometry2POSTGIS(result, 0, srid);
511  sfcgal_geometry_delete(result);
512 
513  PG_RETURN_POINTER(output);
514 }
515 
517 Datum sfcgal_difference(PG_FUNCTION_ARGS)
518 {
519  GSERIALIZED *input0, *input1, *output;
520  sfcgal_geometry_t *geom0, *geom1;
521  sfcgal_geometry_t *result;
522  srid_t srid;
523 
525 
526  input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
527  srid = gserialized_get_srid(input0);
528  input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
529  geom0 = POSTGIS2SFCGALGeometry(input0);
530  PG_FREE_IF_COPY(input0, 0);
531  geom1 = POSTGIS2SFCGALGeometry(input1);
532  PG_FREE_IF_COPY(input1, 1);
533 
534  result = sfcgal_geometry_difference(geom0, geom1);
535  sfcgal_geometry_delete(geom0);
536  sfcgal_geometry_delete(geom1);
537 
538  output = SFCGALGeometry2POSTGIS(result, 0, srid);
539  sfcgal_geometry_delete(result);
540 
541  PG_RETURN_POINTER(output);
542 }
543 
544 
546 Datum sfcgal_difference3D(PG_FUNCTION_ARGS)
547 {
548  GSERIALIZED *input0, *input1, *output;
549  sfcgal_geometry_t *geom0, *geom1;
550  sfcgal_geometry_t *result;
551  srid_t srid;
552 
554 
555  input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
556  srid = gserialized_get_srid(input0);
557  input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
558  geom0 = POSTGIS2SFCGALGeometry(input0);
559  PG_FREE_IF_COPY(input0, 0);
560  geom1 = POSTGIS2SFCGALGeometry(input1);
561  PG_FREE_IF_COPY(input1, 1);
562 
563  result = sfcgal_geometry_difference_3d(geom0, geom1);
564  sfcgal_geometry_delete(geom0);
565  sfcgal_geometry_delete(geom1);
566 
567  output = SFCGALGeometry2POSTGIS(result, 0, srid);
568  sfcgal_geometry_delete(result);
569 
570  PG_RETURN_POINTER(output);
571 }
572 
574 Datum sfcgal_union(PG_FUNCTION_ARGS)
575 {
576  GSERIALIZED *input0, *input1, *output;
577  sfcgal_geometry_t *geom0, *geom1;
578  sfcgal_geometry_t *result;
579  srid_t srid;
580 
582 
583  input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
584  srid = gserialized_get_srid(input0);
585  input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
586  geom0 = POSTGIS2SFCGALGeometry(input0);
587  PG_FREE_IF_COPY(input0, 0);
588  geom1 = POSTGIS2SFCGALGeometry(input1);
589  PG_FREE_IF_COPY(input1, 1);
590 
591  result = sfcgal_geometry_union(geom0, geom1);
592  sfcgal_geometry_delete(geom0);
593  sfcgal_geometry_delete(geom1);
594 
595  output = SFCGALGeometry2POSTGIS(result, 0, srid);
596  sfcgal_geometry_delete(result);
597 
598  PG_RETURN_POINTER(output);
599 }
600 
601 
603 Datum sfcgal_union3D(PG_FUNCTION_ARGS)
604 {
605  GSERIALIZED *input0, *input1, *output;
606  sfcgal_geometry_t *geom0, *geom1;
607  sfcgal_geometry_t *result;
608  srid_t srid;
609 
611 
612  input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
613  srid = gserialized_get_srid(input0);
614  input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
615  geom0 = POSTGIS2SFCGALGeometry(input0);
616  PG_FREE_IF_COPY(input0, 0);
617  geom1 = POSTGIS2SFCGALGeometry(input1);
618  PG_FREE_IF_COPY(input1, 1);
619 
620  result = sfcgal_geometry_union_3d(geom0, geom1);
621  sfcgal_geometry_delete(geom0);
622  sfcgal_geometry_delete(geom1);
623 
624  output = SFCGALGeometry2POSTGIS(result, 0, srid);
625  sfcgal_geometry_delete(result);
626 
627  PG_RETURN_POINTER(output);
628 }
629 
631 Datum sfcgal_volume(PG_FUNCTION_ARGS)
632 {
633  GSERIALIZED *input;
634  sfcgal_geometry_t *geom;
635  double result;
636 
638 
639  input = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
640  geom = POSTGIS2SFCGALGeometry(input);
641 
642  result = sfcgal_geometry_volume(geom);
643  sfcgal_geometry_delete(geom);
644 
645  PG_FREE_IF_COPY(input, 0);
646 
647  PG_RETURN_FLOAT8(result);
648 }
649 
651 Datum sfcgal_minkowski_sum(PG_FUNCTION_ARGS)
652 {
653  GSERIALIZED *input0, *input1, *output;
654  sfcgal_geometry_t *geom0, *geom1;
655  sfcgal_geometry_t *result;
656  srid_t srid;
657 
659 
660  input0 = PG_GETARG_GSERIALIZED_P(0);
661  srid = gserialized_get_srid(input0);
662  input1 = PG_GETARG_GSERIALIZED_P(1);
663  geom0 = POSTGIS2SFCGALGeometry(input0);
664  PG_FREE_IF_COPY(input0, 0);
665  geom1 = POSTGIS2SFCGALGeometry(input1);
666  PG_FREE_IF_COPY(input1, 1);
667 
668  result = sfcgal_geometry_minkowski_sum(geom0, geom1);
669  sfcgal_geometry_delete(geom0);
670  sfcgal_geometry_delete(geom1);
671 
672  output = SFCGALGeometry2POSTGIS(result, 0, srid);
673  sfcgal_geometry_delete(result);
674 
675  PG_RETURN_POINTER(output);
676 }
677 
678 
680 Datum sfcgal_extrude(PG_FUNCTION_ARGS)
681 {
682  GSERIALIZED *input, *output;
683  sfcgal_geometry_t *geom;
684  sfcgal_geometry_t *result;
685  double dx, dy, dz;
686  srid_t srid;
687 
689 
690  input = PG_GETARG_GSERIALIZED_P(0);
691  srid = gserialized_get_srid(input);
692 
693  geom = POSTGIS2SFCGALGeometry(input);
694  PG_FREE_IF_COPY(input, 0);
695 
696  dx = PG_GETARG_FLOAT8(1);
697  dy = PG_GETARG_FLOAT8(2);
698  dz = PG_GETARG_FLOAT8(3);
699 
700  result = sfcgal_geometry_extrude(geom, dx, dy, dz);
701  sfcgal_geometry_delete(geom);
702 
703  output = SFCGALGeometry2POSTGIS(result, 0, srid);
704  sfcgal_geometry_delete(result);
705 
706  PG_RETURN_POINTER(output);
707 }
708 
710 Datum postgis_sfcgal_version(PG_FUNCTION_ARGS)
711 {
712  const char *ver = lwgeom_sfcgal_version();
713  text *result = cstring2text(ver);
714  PG_RETURN_POINTER(result);
715 }
716 
718 Datum sfcgal_is_solid(PG_FUNCTION_ARGS)
719 {
720  int result;
721  GSERIALIZED *input = PG_GETARG_GSERIALIZED_P(0);
722  LWGEOM *lwgeom = lwgeom_from_gserialized(input);
723  PG_FREE_IF_COPY(input, 0);
724  if (! lwgeom)
725  {
726  lwerror("sfcgal_is_solid: Unable to deserialize input");
727  }
728  result = FLAGS_GET_SOLID( lwgeom->flags );
729 
730  lwgeom_free(lwgeom);
731 
732  PG_RETURN_BOOL(result);
733 }
734 
736 Datum sfcgal_make_solid(PG_FUNCTION_ARGS)
737 {
738  GSERIALIZED *output;
739  GSERIALIZED *input = PG_GETARG_GSERIALIZED_P(0);
740  LWGEOM *lwgeom = lwgeom_from_gserialized(input);
741  PG_FREE_IF_COPY(input, 0);
742  if (! lwgeom)
743  {
744  lwerror("sfcgal_make_solid: Unable to deserialize input");
745  }
746 
747  FLAGS_SET_SOLID( lwgeom->flags, 1);
748 
749  output = geometry_serialize( lwgeom );
750  lwgeom_free(lwgeom);
751 
752  PG_RETURN_POINTER(output);
753 }
754 
GSERIALIZED * SFCGALPreparedGeometry2POSTGIS(const sfcgal_prepared_geometry_t *geom, int force3D)
#define POSTGIS_SFCGAL_VERSION
Definition: sqldefines.h:14
Datum sfcgal_volume(PG_FUNCTION_ARGS)
#define FLAGS_SET_SOLID(flags, value)
Definition: liblwgeom.h:135
Datum sfcgal_is_planar(PG_FUNCTION_ARGS)
Datum sfcgal_extrude(PG_FUNCTION_ARGS)
void lwfree(void *mem)
Definition: lwutil.c:214
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Datum sfcgal_union3D(PG_FUNCTION_ARGS)
Datum sfcgal_approximate_medial_axis(PG_FUNCTION_ARGS)
Datum sfcgal_is_solid(PG_FUNCTION_ARGS)
uint8_t flags
Definition: liblwgeom.h:381
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1050
sfcgal_geometry_t * POSTGIS2SFCGALGeometry(GSERIALIZED *pglwgeom)
GSERIALIZED * SFCGALGeometry2POSTGIS(const sfcgal_geometry_t *geom, int force3D, int SRID)
#define FLAGS_GET_SOLID(flags)
Definition: liblwgeom.h:129
Datum sfcgal_distance3D(PG_FUNCTION_ARGS)
Datum sfcgal_minkowski_sum(PG_FUNCTION_ARGS)
Datum sfcgal_orientation(PG_FUNCTION_ARGS)
Datum sfcgal_make_solid(PG_FUNCTION_ARGS)
const char * lwgeom_sfcgal_version()
Datum sfcgal_force_lhr(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(sfcgal_from_ewkt)
Datum sfcgal_intersection3D(PG_FUNCTION_ARGS)
sfcgal_geometry_t * LWGEOM2SFCGAL(const LWGEOM *geom)
Datum sfcgal_area3D(PG_FUNCTION_ARGS)
Datum sfcgal_triangulate(PG_FUNCTION_ARGS)
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:61
Datum sfcgal_difference3D(PG_FUNCTION_ARGS)
Datum sfcgal_intersects3D(PG_FUNCTION_ARGS)
char * text2cstring(const text *textptr)
Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS)
Datum postgis_sfcgal_version(PG_FUNCTION_ARGS)
sfcgal_prepared_geometry_t * POSTGIS2SFCGALPreparedGeometry(GSERIALIZED *pglwgeom)
Datum sfcgal_union(PG_FUNCTION_ARGS)
void sfcgal_postgis_init(void)
Datum sfcgal_from_ewkt(PG_FUNCTION_ARGS)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
Datum sfcgal_intersects(PG_FUNCTION_ARGS)
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:599
Datum sfcgal_distance(PG_FUNCTION_ARGS)
Datum sfcgal_intersection(PG_FUNCTION_ARGS)
Datum sfcgal_area(PG_FUNCTION_ARGS)
Datum sfcgal_difference(PG_FUNCTION_ARGS)
void * lwalloc(size_t size)
Definition: lwutil.c:199
static int __sfcgal_init
int lwgeom_needs_bbox(const LWGEOM *geom)
Check whether or not a lwgeom is big enough to warrant a bounding box.
Definition: lwgeom.c:1103
Datum sfcgal_tesselate(PG_FUNCTION_ARGS)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
LWGEOM * SFCGAL2LWGEOM(const sfcgal_geometry_t *geom, int force3D, int srid)
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:69