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