PostGIS  2.5.1dev-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  * 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 
26 #include "postgres.h"
27 #include "fmgr.h"
28 #include "utils/builtins.h"
29 #include "../liblwgeom/liblwgeom.h"
30 
31 #include "lwgeom_pg.h"
32 #include "lwgeom_sfcgal.h"
33 #include "../postgis_config.h"
34 
35 
36 Datum postgis_sfcgal_version(PG_FUNCTION_ARGS);
37 
38 Datum sfcgal_from_ewkt(PG_FUNCTION_ARGS);
39 Datum sfcgal_distance(PG_FUNCTION_ARGS);
40 Datum sfcgal_distance3D(PG_FUNCTION_ARGS);
41 Datum sfcgal_area(PG_FUNCTION_ARGS);
42 Datum sfcgal_area3D(PG_FUNCTION_ARGS);
43 Datum sfcgal_intersects(PG_FUNCTION_ARGS);
44 Datum sfcgal_intersects3D(PG_FUNCTION_ARGS);
45 Datum sfcgal_intersection(PG_FUNCTION_ARGS);
46 Datum sfcgal_intersection3D(PG_FUNCTION_ARGS);
47 Datum sfcgal_difference(PG_FUNCTION_ARGS);
48 Datum sfcgal_difference3D(PG_FUNCTION_ARGS);
49 Datum sfcgal_union(PG_FUNCTION_ARGS);
50 Datum sfcgal_union3D(PG_FUNCTION_ARGS);
51 Datum sfcgal_volume(PG_FUNCTION_ARGS);
52 Datum sfcgal_extrude(PG_FUNCTION_ARGS);
53 Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS);
54 Datum sfcgal_approximate_medial_axis(PG_FUNCTION_ARGS);
55 Datum sfcgal_is_planar(PG_FUNCTION_ARGS);
56 Datum sfcgal_orientation(PG_FUNCTION_ARGS);
57 Datum sfcgal_force_lhr(PG_FUNCTION_ARGS);
58 Datum sfcgal_triangulate(PG_FUNCTION_ARGS);
59 Datum sfcgal_tesselate(PG_FUNCTION_ARGS);
60 Datum sfcgal_minkowski_sum(PG_FUNCTION_ARGS);
61 Datum sfcgal_make_solid(PG_FUNCTION_ARGS);
62 Datum sfcgal_is_solid(PG_FUNCTION_ARGS);
63 
64 
66 char* text_to_cstring(const text *textptr);
67 
68 static int __sfcgal_init = 0;
69 
71 {
72  if ( ! __sfcgal_init ) {
73  sfcgal_init();
74  sfcgal_set_error_handlers((sfcgal_error_handler_t) lwpgnotice, (sfcgal_error_handler_t) lwpgerror);
75  sfcgal_set_alloc_handlers(lwalloc, lwfree);
76  __sfcgal_init = 1;
77  }
78 }
79 
80 
81 /* Conversion from GSERIALIZED* to SFCGAL::Geometry */
82 sfcgal_geometry_t* POSTGIS2SFCGALGeometry(GSERIALIZED *pglwgeom)
83 {
84  sfcgal_geometry_t* g;
85  LWGEOM *lwgeom = lwgeom_from_gserialized(pglwgeom);
86 
87  if (! lwgeom)
88  {
89  lwpgerror("POSTGIS2SFCGALGeometry: Unable to deserialize input");
90  }
91  g = LWGEOM2SFCGAL(lwgeom);
92  lwgeom_free(lwgeom);
93 
94  return g;
95 }
96 
97 
98 /* Conversion from GSERIALIZED* to SFCGAL::PreparedGeometry */
99 sfcgal_prepared_geometry_t* POSTGIS2SFCGALPreparedGeometry(GSERIALIZED *pglwgeom)
100 {
101  sfcgal_geometry_t* g;
102  LWGEOM *lwgeom = lwgeom_from_gserialized(pglwgeom);
103 
104  if (!lwgeom)
105  {
106  lwpgerror("POSTGIS2SFCGALPreparedGeometry: Unable to deserialize input");
107  }
108  g = LWGEOM2SFCGAL(lwgeom);
109 
110  lwgeom_free(lwgeom);
111 
112  return sfcgal_prepared_geometry_create_from_geometry(g, gserialized_get_srid(pglwgeom));
113 }
114 
115 
116 /* Conversion from SFCGAL::Geometry to GSERIALIZED */
117 GSERIALIZED* SFCGALGeometry2POSTGIS(const sfcgal_geometry_t* geom, int force3D, int SRID)
118 {
119  GSERIALIZED *result;
120  LWGEOM* lwgeom = SFCGAL2LWGEOM(geom, force3D, SRID);
121 
122  if (lwgeom_needs_bbox(lwgeom) == LW_TRUE)
123  lwgeom_add_bbox(lwgeom);
124 
125  result = geometry_serialize(lwgeom);
126  lwgeom_free(lwgeom);
127 
128  return result;
129 }
130 
131 
132 /* Conversion from SFCGAL::PreparedGeometry to GSERIALIZED */
133 GSERIALIZED* SFCGALPreparedGeometry2POSTGIS(const sfcgal_prepared_geometry_t* geom, int force3D)
134 {
135  return SFCGALGeometry2POSTGIS(sfcgal_prepared_geometry_geometry(geom),
136  force3D, sfcgal_prepared_geometry_srid(geom));
137 }
138 
139 
140 /* Conversion from EWKT to GSERIALIZED */
142 Datum sfcgal_from_ewkt(PG_FUNCTION_ARGS)
143 {
144  GSERIALIZED* result;
145  sfcgal_prepared_geometry_t* g;
146  text *wkttext = PG_GETARG_TEXT_P(0);
147  char *cstring = text_to_cstring(wkttext);
148 
150 
151  g = sfcgal_io_read_ewkt( cstring, strlen(cstring) );
152 
153  result = SFCGALPreparedGeometry2POSTGIS( g, 0 );
154  sfcgal_prepared_geometry_delete( g );
155  PG_RETURN_POINTER(result);
156 }
157 
158 
160 Datum sfcgal_area(PG_FUNCTION_ARGS)
161  {
162  GSERIALIZED *input;
163  sfcgal_geometry_t *geom;
164  double result;
165 
167 
168  input = PG_GETARG_GSERIALIZED_P(0);
169  geom = POSTGIS2SFCGALGeometry(input);
170 
171  result = sfcgal_geometry_area(geom);
172  sfcgal_geometry_delete(geom);
173 
174  PG_FREE_IF_COPY(input, 0);
175 
176  PG_RETURN_FLOAT8(result);
177 }
178 
179 
181 Datum sfcgal_area3D(PG_FUNCTION_ARGS)
182  {
183  GSERIALIZED *input;
184  sfcgal_geometry_t *geom;
185  double result;
186 
188 
189  input = PG_GETARG_GSERIALIZED_P(0);
190  geom = POSTGIS2SFCGALGeometry(input);
191 
192  result = sfcgal_geometry_area_3d(geom);
193  sfcgal_geometry_delete(geom);
194 
195  PG_FREE_IF_COPY(input, 0);
196 
197  PG_RETURN_FLOAT8(result);
198 }
199 
200 
202 Datum sfcgal_is_planar(PG_FUNCTION_ARGS)
203 {
204  GSERIALIZED *input;
205  sfcgal_geometry_t *geom;
206  int result;
207 
209 
210  input = PG_GETARG_GSERIALIZED_P(0);
211  geom = POSTGIS2SFCGALGeometry(input);
212 
213  result = sfcgal_geometry_is_planar(geom);
214  sfcgal_geometry_delete(geom);
215 
216  PG_FREE_IF_COPY(input, 0);
217 
218  PG_RETURN_BOOL(result);
219 }
220 
221 
223 Datum sfcgal_orientation(PG_FUNCTION_ARGS)
224 {
225  GSERIALIZED *input;
226  sfcgal_geometry_t *geom;
227  int result;
228 
230 
231  input = PG_GETARG_GSERIALIZED_P(0);
232  geom = POSTGIS2SFCGALGeometry(input);
233 
234  result = sfcgal_geometry_orientation(geom);
235  sfcgal_geometry_delete(geom);
236 
237  PG_FREE_IF_COPY(input, 0);
238 
239  PG_RETURN_INT32(result);
240 }
241 
242 
244 Datum sfcgal_intersects(PG_FUNCTION_ARGS)
245 {
246  GSERIALIZED *input0, *input1;
247  sfcgal_geometry_t *geom0, *geom1;
248  int result;
249 
251 
252  input0 = PG_GETARG_GSERIALIZED_P(0);
253  input1 = PG_GETARG_GSERIALIZED_P(1);
254  geom0 = POSTGIS2SFCGALGeometry(input0);
255  PG_FREE_IF_COPY(input0, 0);
256  geom1 = POSTGIS2SFCGALGeometry(input1);
257  PG_FREE_IF_COPY(input1, 1);
258 
259  result = sfcgal_geometry_intersects(geom0, geom1);
260  sfcgal_geometry_delete(geom0);
261  sfcgal_geometry_delete(geom1);
262 
263  PG_RETURN_BOOL(result);
264 }
265 
266 
268 Datum sfcgal_intersects3D(PG_FUNCTION_ARGS)
269 {
270  GSERIALIZED *input0, *input1;
271  sfcgal_geometry_t *geom0, *geom1;
272  int result;
273 
275 
276  input0 = PG_GETARG_GSERIALIZED_P(0);
277  input1 = PG_GETARG_GSERIALIZED_P(1);
278  geom0 = POSTGIS2SFCGALGeometry(input0);
279  PG_FREE_IF_COPY(input0, 0);
280  geom1 = POSTGIS2SFCGALGeometry(input1);
281  PG_FREE_IF_COPY(input1, 1);
282 
283  result = sfcgal_geometry_intersects_3d(geom0, geom1);
284  sfcgal_geometry_delete(geom0);
285  sfcgal_geometry_delete(geom1);
286 
287  PG_RETURN_BOOL(result);
288 }
289 
290 
292 Datum sfcgal_distance(PG_FUNCTION_ARGS)
293 {
294  GSERIALIZED *input0, *input1;
295  sfcgal_geometry_t *geom0, *geom1;
296  double result;
297 
299 
300  input0 = PG_GETARG_GSERIALIZED_P(0);
301  input1 = PG_GETARG_GSERIALIZED_P(1);
302  geom0 = POSTGIS2SFCGALGeometry(input0);
303  PG_FREE_IF_COPY(input0, 0);
304  geom1 = POSTGIS2SFCGALGeometry(input1);
305  PG_FREE_IF_COPY(input1, 1);
306 
307  result = sfcgal_geometry_distance(geom0, geom1);
308  sfcgal_geometry_delete(geom0);
309  sfcgal_geometry_delete(geom1);
310 
311  PG_RETURN_FLOAT8(result);
312 }
313 
314 
316 Datum sfcgal_distance3D(PG_FUNCTION_ARGS)
317 {
318  GSERIALIZED *input0, *input1;
319  sfcgal_geometry_t *geom0, *geom1;
320  double result;
321 
323 
324  input0 = PG_GETARG_GSERIALIZED_P(0);
325  input1 = PG_GETARG_GSERIALIZED_P(1);
326  geom0 = POSTGIS2SFCGALGeometry(input0);
327  PG_FREE_IF_COPY(input0, 0);
328  geom1 = POSTGIS2SFCGALGeometry(input1);
329  PG_FREE_IF_COPY(input1, 1);
330 
331  result = sfcgal_geometry_distance_3d(geom0, geom1);
332  sfcgal_geometry_delete(geom0);
333  sfcgal_geometry_delete(geom1);
334 
335  PG_RETURN_FLOAT8(result);
336 }
337 
338 
340 Datum sfcgal_tesselate(PG_FUNCTION_ARGS)
341 {
342  GSERIALIZED *input, *output;
343  sfcgal_geometry_t *geom;
344  sfcgal_geometry_t *result;
345  srid_t srid;
346 
348 
349  input = PG_GETARG_GSERIALIZED_P(0);
350  srid = gserialized_get_srid(input);
351  geom = POSTGIS2SFCGALGeometry(input);
352  PG_FREE_IF_COPY(input, 0);
353 
354  result = sfcgal_geometry_tesselate(geom);
355  sfcgal_geometry_delete(geom);
356 
357  output = SFCGALGeometry2POSTGIS(result, 0, srid);
358  sfcgal_geometry_delete(result);
359 
360  PG_RETURN_POINTER(output);
361 }
362 
363 
365 Datum sfcgal_triangulate(PG_FUNCTION_ARGS)
366 {
367  GSERIALIZED *input, *output;
368  sfcgal_geometry_t *geom;
369  sfcgal_geometry_t *result;
370  srid_t srid;
371 
373 
374  input = PG_GETARG_GSERIALIZED_P(0);
375  srid = gserialized_get_srid(input);
376  geom = POSTGIS2SFCGALGeometry(input);
377  PG_FREE_IF_COPY(input, 0);
378 
379  result = sfcgal_geometry_triangulate_2dz(geom);
380  sfcgal_geometry_delete(geom);
381 
382  output = SFCGALGeometry2POSTGIS(result, 0, srid);
383  sfcgal_geometry_delete(result);
384 
385  PG_RETURN_POINTER(output);
386 }
387 
388 
390 Datum sfcgal_force_lhr(PG_FUNCTION_ARGS)
391 {
392  GSERIALIZED *input, *output;
393  sfcgal_geometry_t *geom;
394  sfcgal_geometry_t *result;
395  srid_t srid;
396 
398 
399  input = PG_GETARG_GSERIALIZED_P(0);
400  srid = gserialized_get_srid(input);
401  geom = POSTGIS2SFCGALGeometry(input);
402  PG_FREE_IF_COPY(input, 0);
403 
404  result = sfcgal_geometry_force_lhr(geom);
405  sfcgal_geometry_delete(geom);
406 
407  output = SFCGALGeometry2POSTGIS(result, 0, srid);
408  sfcgal_geometry_delete(result);
409 
410  PG_RETURN_POINTER(output);
411 }
412 
413 
415 Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS)
416 {
417  GSERIALIZED *input, *output;
418  sfcgal_geometry_t *geom;
419  sfcgal_geometry_t *result;
420  srid_t srid;
421 
423 
424  input = PG_GETARG_GSERIALIZED_P(0);
425  srid = gserialized_get_srid(input);
426  geom = POSTGIS2SFCGALGeometry(input);
427  PG_FREE_IF_COPY(input, 0);
428 
429  result = sfcgal_geometry_straight_skeleton(geom);
430  sfcgal_geometry_delete(geom);
431 
432  output = SFCGALGeometry2POSTGIS(result, 0, srid);
433  sfcgal_geometry_delete(result);
434 
435  PG_RETURN_POINTER(output);
436 }
437 
439 Datum sfcgal_approximate_medial_axis(PG_FUNCTION_ARGS)
440 {
441 #if POSTGIS_SFCGAL_VERSION < 12
442  lwpgerror("The SFCGAL version this PostGIS binary "
443  "was compiled against (%d) doesn't support "
444  "'sfcgal_geometry_approximate_medial_axis' function (1.2.0+ required)",
446  PG_RETURN_NULL();
447 #else /* POSTGIS_SFCGAL_VERSION >= 12 */
448  GSERIALIZED *input, *output;
449  sfcgal_geometry_t *geom;
450  sfcgal_geometry_t *result;
451  srid_t srid;
452 
454 
455  input = PG_GETARG_GSERIALIZED_P(0);
456  srid = gserialized_get_srid(input);
457  geom = POSTGIS2SFCGALGeometry(input);
458  PG_FREE_IF_COPY(input, 0);
459 
460  result = sfcgal_geometry_approximate_medial_axis(geom);
461  sfcgal_geometry_delete(geom);
462 
463  output = SFCGALGeometry2POSTGIS(result, 0, srid);
464  sfcgal_geometry_delete(result);
465 
466  PG_RETURN_POINTER(output);
467 #endif /* POSTGIS_SFCGAL_VERSION >= 12 */
468 }
469 
470 
472 Datum sfcgal_intersection(PG_FUNCTION_ARGS)
473 {
474  GSERIALIZED *input0, *input1, *output;
475  sfcgal_geometry_t *geom0, *geom1;
476  sfcgal_geometry_t *result;
477  srid_t srid;
478 
480 
481  input0 = PG_GETARG_GSERIALIZED_P(0);
482  srid = gserialized_get_srid(input0);
483  input1 = PG_GETARG_GSERIALIZED_P(1);
484  geom0 = POSTGIS2SFCGALGeometry(input0);
485  PG_FREE_IF_COPY(input0, 0);
486  geom1 = POSTGIS2SFCGALGeometry(input1);
487  PG_FREE_IF_COPY(input1, 1);
488 
489  result = sfcgal_geometry_intersection(geom0, geom1);
490  sfcgal_geometry_delete(geom0);
491  sfcgal_geometry_delete(geom1);
492 
493  output = SFCGALGeometry2POSTGIS(result, 0, srid);
494  sfcgal_geometry_delete(result);
495 
496  PG_RETURN_POINTER(output);
497 }
498 
499 
501 Datum sfcgal_intersection3D(PG_FUNCTION_ARGS)
502 {
503  GSERIALIZED *input0, *input1, *output;
504  sfcgal_geometry_t *geom0, *geom1;
505  sfcgal_geometry_t *result;
506  srid_t srid;
507 
509 
510  input0 = PG_GETARG_GSERIALIZED_P(0);
511  srid = gserialized_get_srid(input0);
512  input1 = PG_GETARG_GSERIALIZED_P(1);
513  geom0 = POSTGIS2SFCGALGeometry(input0);
514  PG_FREE_IF_COPY(input0, 0);
515  geom1 = POSTGIS2SFCGALGeometry(input1);
516  PG_FREE_IF_COPY(input1, 1);
517 
518  result = sfcgal_geometry_intersection_3d(geom0, geom1);
519  sfcgal_geometry_delete(geom0);
520  sfcgal_geometry_delete(geom1);
521 
522  output = SFCGALGeometry2POSTGIS(result, 0, srid);
523  sfcgal_geometry_delete(result);
524 
525  PG_RETURN_POINTER(output);
526 }
527 
529 Datum sfcgal_difference(PG_FUNCTION_ARGS)
530 {
531  GSERIALIZED *input0, *input1, *output;
532  sfcgal_geometry_t *geom0, *geom1;
533  sfcgal_geometry_t *result;
534  srid_t srid;
535 
537 
538  input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
539  srid = gserialized_get_srid(input0);
540  input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
541  geom0 = POSTGIS2SFCGALGeometry(input0);
542  PG_FREE_IF_COPY(input0, 0);
543  geom1 = POSTGIS2SFCGALGeometry(input1);
544  PG_FREE_IF_COPY(input1, 1);
545 
546  result = sfcgal_geometry_difference(geom0, geom1);
547  sfcgal_geometry_delete(geom0);
548  sfcgal_geometry_delete(geom1);
549 
550  output = SFCGALGeometry2POSTGIS(result, 0, srid);
551  sfcgal_geometry_delete(result);
552 
553  PG_RETURN_POINTER(output);
554 }
555 
556 
558 Datum sfcgal_difference3D(PG_FUNCTION_ARGS)
559 {
560  GSERIALIZED *input0, *input1, *output;
561  sfcgal_geometry_t *geom0, *geom1;
562  sfcgal_geometry_t *result;
563  srid_t srid;
564 
566 
567  input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
568  srid = gserialized_get_srid(input0);
569  input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
570  geom0 = POSTGIS2SFCGALGeometry(input0);
571  PG_FREE_IF_COPY(input0, 0);
572  geom1 = POSTGIS2SFCGALGeometry(input1);
573  PG_FREE_IF_COPY(input1, 1);
574 
575  result = sfcgal_geometry_difference_3d(geom0, geom1);
576  sfcgal_geometry_delete(geom0);
577  sfcgal_geometry_delete(geom1);
578 
579  output = SFCGALGeometry2POSTGIS(result, 0, srid);
580  sfcgal_geometry_delete(result);
581 
582  PG_RETURN_POINTER(output);
583 }
584 
586 Datum sfcgal_union(PG_FUNCTION_ARGS)
587 {
588  GSERIALIZED *input0, *input1, *output;
589  sfcgal_geometry_t *geom0, *geom1;
590  sfcgal_geometry_t *result;
591  srid_t srid;
592 
594 
595  input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
596  srid = gserialized_get_srid(input0);
597  input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
598  geom0 = POSTGIS2SFCGALGeometry(input0);
599  PG_FREE_IF_COPY(input0, 0);
600  geom1 = POSTGIS2SFCGALGeometry(input1);
601  PG_FREE_IF_COPY(input1, 1);
602 
603  result = sfcgal_geometry_union(geom0, geom1);
604  sfcgal_geometry_delete(geom0);
605  sfcgal_geometry_delete(geom1);
606 
607  output = SFCGALGeometry2POSTGIS(result, 0, srid);
608  sfcgal_geometry_delete(result);
609 
610  PG_RETURN_POINTER(output);
611 }
612 
613 
615 Datum sfcgal_union3D(PG_FUNCTION_ARGS)
616 {
617  GSERIALIZED *input0, *input1, *output;
618  sfcgal_geometry_t *geom0, *geom1;
619  sfcgal_geometry_t *result;
620  srid_t srid;
621 
623 
624  input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
625  srid = gserialized_get_srid(input0);
626  input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
627  geom0 = POSTGIS2SFCGALGeometry(input0);
628  PG_FREE_IF_COPY(input0, 0);
629  geom1 = POSTGIS2SFCGALGeometry(input1);
630  PG_FREE_IF_COPY(input1, 1);
631 
632  result = sfcgal_geometry_union_3d(geom0, geom1);
633  sfcgal_geometry_delete(geom0);
634  sfcgal_geometry_delete(geom1);
635 
636  output = SFCGALGeometry2POSTGIS(result, 0, srid);
637  sfcgal_geometry_delete(result);
638 
639  PG_RETURN_POINTER(output);
640 }
641 
643 Datum sfcgal_volume(PG_FUNCTION_ARGS)
644 {
645  GSERIALIZED *input;
646  sfcgal_geometry_t *geom;
647  double result;
648 
650 
651  input = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
652  geom = POSTGIS2SFCGALGeometry(input);
653 
654  result = sfcgal_geometry_volume(geom);
655  sfcgal_geometry_delete(geom);
656 
657  PG_FREE_IF_COPY(input, 0);
658 
659  PG_RETURN_FLOAT8(result);
660 }
661 
663 Datum sfcgal_minkowski_sum(PG_FUNCTION_ARGS)
664 {
665  GSERIALIZED *input0, *input1, *output;
666  sfcgal_geometry_t *geom0, *geom1;
667  sfcgal_geometry_t *result;
668  srid_t srid;
669 
671 
672  input0 = PG_GETARG_GSERIALIZED_P(0);
673  srid = gserialized_get_srid(input0);
674  input1 = PG_GETARG_GSERIALIZED_P(1);
675  geom0 = POSTGIS2SFCGALGeometry(input0);
676  PG_FREE_IF_COPY(input0, 0);
677  geom1 = POSTGIS2SFCGALGeometry(input1);
678  PG_FREE_IF_COPY(input1, 1);
679 
680  result = sfcgal_geometry_minkowski_sum(geom0, geom1);
681  sfcgal_geometry_delete(geom0);
682  sfcgal_geometry_delete(geom1);
683 
684  output = SFCGALGeometry2POSTGIS(result, 0, srid);
685  sfcgal_geometry_delete(result);
686 
687  PG_RETURN_POINTER(output);
688 }
689 
690 
692 Datum sfcgal_extrude(PG_FUNCTION_ARGS)
693 {
694  GSERIALIZED *input, *output;
695  sfcgal_geometry_t *geom;
696  sfcgal_geometry_t *result;
697  double dx, dy, dz;
698  srid_t srid;
699 
701 
702  input = PG_GETARG_GSERIALIZED_P(0);
703  srid = gserialized_get_srid(input);
704 
705  geom = POSTGIS2SFCGALGeometry(input);
706  PG_FREE_IF_COPY(input, 0);
707 
708  dx = PG_GETARG_FLOAT8(1);
709  dy = PG_GETARG_FLOAT8(2);
710  dz = PG_GETARG_FLOAT8(3);
711 
712  result = sfcgal_geometry_extrude(geom, dx, dy, dz);
713  sfcgal_geometry_delete(geom);
714 
715  output = SFCGALGeometry2POSTGIS(result, 0, srid);
716  sfcgal_geometry_delete(result);
717 
718  PG_RETURN_POINTER(output);
719 }
720 
722 Datum postgis_sfcgal_version(PG_FUNCTION_ARGS)
723 {
724  const char *ver = lwgeom_sfcgal_version();
725  text *result = cstring_to_text(ver);
726  PG_RETURN_POINTER(result);
727 }
728 
730 Datum sfcgal_is_solid(PG_FUNCTION_ARGS)
731 {
732  int result;
733  GSERIALIZED *input = PG_GETARG_GSERIALIZED_P(0);
734  LWGEOM *lwgeom = lwgeom_from_gserialized(input);
735  PG_FREE_IF_COPY(input, 0);
736  if (! lwgeom)
737  {
738  elog(ERROR, "sfcgal_is_solid: Unable to deserialize input");
739  }
740  result = FLAGS_GET_SOLID( lwgeom->flags );
741 
742  lwgeom_free(lwgeom);
743 
744  PG_RETURN_BOOL(result);
745 }
746 
748 Datum sfcgal_make_solid(PG_FUNCTION_ARGS)
749 {
750  GSERIALIZED *output;
751  GSERIALIZED *input = PG_GETARG_GSERIALIZED_P(0);
752  LWGEOM *lwgeom = lwgeom_from_gserialized(input);
753  if (! lwgeom)
754  {
755  elog(ERROR, "sfcgal_make_solid: Unable to deserialize input");
756  }
757 
758  FLAGS_SET_SOLID( lwgeom->flags, 1);
759 
760  output = geometry_serialize( lwgeom );
761  lwgeom_free(lwgeom);
762  PG_FREE_IF_COPY(input, 0);
763  PG_RETURN_POINTER(output);
764 }
765 
GSERIALIZED * SFCGALPreparedGeometry2POSTGIS(const sfcgal_prepared_geometry_t *geom, int force3D)
char * text_to_cstring(const text *textptr)
#define POSTGIS_SFCGAL_VERSION
Definition: sqldefines.h:14
Datum sfcgal_volume(PG_FUNCTION_ARGS)
#define FLAGS_SET_SOLID(flags, value)
Definition: liblwgeom.h:150
Datum sfcgal_is_planar(PG_FUNCTION_ARGS)
Datum sfcgal_extrude(PG_FUNCTION_ARGS)
void lwfree(void *mem)
Definition: lwutil.c:244
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:399
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
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:144
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:75
Datum sfcgal_difference3D(PG_FUNCTION_ARGS)
Datum sfcgal_intersects3D(PG_FUNCTION_ARGS)
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:686
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:229
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:1197
Datum sfcgal_tesselate(PG_FUNCTION_ARGS)
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:99