]> granicus.if.org Git - postgis/commitdiff
Add suport for SFCGAL 1.1. #3117. Apply patch written by Vincent Mora
authorOlivier Courtin <olivier.courtin@camptocamp.com>
Thu, 25 Jun 2015 20:44:47 +0000 (20:44 +0000)
committerOlivier Courtin <olivier.courtin@camptocamp.com>
Thu, 25 Jun 2015 20:44:47 +0000 (20:44 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@13709 b70326c6-7e19-0410-871a-916f4a2858ee

doc/reference_sfcgal.xml
postgis/lwgeom_backend_api.c
postgis/lwgeom_geos.c
postgis/lwgeom_geos.h
postgis/lwgeom_sfcgal.c
postgis/lwgeom_sfcgal.h
postgis/sfcgal.sql.in
regress/sfcgal/concave_hull.sql
regress/sfcgal/empty.sql
regress/sfcgal/empty_expected
regress/sfcgal/regress_ogc_expected

index 830d88027a1a0ca4d20e88e9fe182faf14f1cb81..860dd214e55715253e54fe291eb239ffbfbe9562 100644 (file)
@@ -449,6 +449,63 @@ FROM  ST_GeomFromText('LINESTRING Z (2 2 6,1.5 1.5 7,1 1 8,0.5 0.5 8,0 0 10)') A
 
        </refentry>
 
+       <refentry id="ST_3DDifference">
+         <refnamediv>
+               <refname>ST_3DDifference</refname>
+
+               <refpurpose>Perform 3D difference</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>geometry <function>ST_3DDifference</function></funcdef>
+                       <paramdef><type>geometry</type> <parameter>geom1</parameter></paramdef>
+                       <paramdef><type>geometry</type> <parameter>geom2</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Availability: 2.2.0</para>
+               <para>&sfcgal_required;</para>
+               <para>&Z_support;</para>
+               <para>&P_support;</para>
+               <para>&T_support;</para>
+         </refsection>
+       </refentry>
+
+       <refentry id="ST_3DUnion">
+         <refnamediv>
+               <refname>ST_3DUnion</refname>
+
+               <refpurpose>Perform 3D union</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>geometry <function>ST_3DUnion</function></funcdef>
+                       <paramdef><type>geometry</type> <parameter>geom1</parameter></paramdef>
+                       <paramdef><type>geometry</type> <parameter>geom2</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Availability: 2.2.0</para>
+               <para>&sfcgal_required;</para>
+               <para>&Z_support;</para>
+               <para>&P_support;</para>
+               <para>&T_support;</para>
+         </refsection>
+       </refentry>
+
+
        <refentry id="ST_3DArea">
          <refnamediv>
                <refname>ST_3DArea</refname>
@@ -583,4 +640,90 @@ FROM  ST_GeomFromText('LINESTRING Z (2 2 6,1.5 1.5 7,1 1 8,0.5 0.5 8,0 0 10)') A
 
        </refentry>
 
+       <refentry id="ST_Volume">
+         <refnamediv>
+               <refname>ST_Volume</refname>
+
+               <refpurpose>Computes the volume.</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>float<function>ST_Volume</function></funcdef>
+                       <paramdef><type>geometry</type> <parameter>geom1</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Availability: 2.2.0</para>
+               <para>&sfcgal_required;</para>
+               <para>&Z_support;</para>
+               <para>&P_support;</para>
+               <para>&T_support;</para>
+         </refsection>
+
+       </refentry>
+
+       <refentry id="ST_MakeSolid">
+         <refnamediv>
+               <refname>ST_MakeSolid</refname>
+
+               <refpurpose>Cast the geometry into a solid. No check is performed. To obtain a valid solid, the input geometry must be a closed Polyhedral Surface or a closed TIN.</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>geometry<function>ST_MakeSolid</function></funcdef>
+                       <paramdef><type>geometry</type> <parameter>geom1</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Availability: 2.2.0</para>
+               <para>&sfcgal_required;</para>
+               <para>&Z_support;</para>
+               <para>&P_support;</para>
+               <para>&T_support;</para>
+         </refsection>
+
+       </refentry>
+
+       <refentry id="ST_IsSolid">
+         <refnamediv>
+               <refname>ST_IsSolid</refname>
+
+               <refpurpose>Test if the geometry is a solid. No validity check is performed.</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>boolean<function>ST_IsSolid</function></funcdef>
+                       <paramdef><type>geometry</type> <parameter>geom1</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+               <para>Availability: 2.2.0</para>
+               <para>&sfcgal_required;</para>
+               <para>&Z_support;</para>
+               <para>&P_support;</para>
+               <para>&T_support;</para>
+         </refsection>
+
+       </refentry>
+
+
+
 </sect1>
index 621a25fb4ef78f906d6ce7ab6b7b7c62cbe1da34..2259869faf6e929668600cac4a2c34ee09219e08 100644 (file)
@@ -29,6 +29,8 @@
 Datum intersects(PG_FUNCTION_ARGS);
 Datum intersects3d(PG_FUNCTION_ARGS);
 Datum intersection(PG_FUNCTION_ARGS);
+Datum difference(PG_FUNCTION_ARGS);
+Datum geomunion(PG_FUNCTION_ARGS);
 Datum area(PG_FUNCTION_ARGS);
 Datum distance(PG_FUNCTION_ARGS);
 Datum distance3d(PG_FUNCTION_ARGS);
@@ -42,6 +44,8 @@ struct lwgeom_backend_definition
     Datum (*intersects_fn)    (PG_FUNCTION_ARGS);
     Datum (*intersects3d_fn)  (PG_FUNCTION_ARGS);
     Datum (*intersection_fn)  (PG_FUNCTION_ARGS);
+    Datum (*difference_fn)    (PG_FUNCTION_ARGS);
+    Datum (*union_fn)         (PG_FUNCTION_ARGS);
     Datum (*area_fn)          (PG_FUNCTION_ARGS);
     Datum (*distance_fn)      (PG_FUNCTION_ARGS);
     Datum (*distance3d_fn)    (PG_FUNCTION_ARGS);
@@ -58,6 +62,8 @@ struct lwgeom_backend_definition lwgeom_backends[LWGEOM_NUM_BACKENDS] = {
       .intersects_fn    = geos_intersects,
       .intersects3d_fn  = intersects3d_dwithin,
       .intersection_fn  = geos_intersection,
+      .difference_fn    = geos_difference,
+      .union_fn         = geos_geomunion,
       .area_fn          = LWGEOM_area_polygon,
       .distance_fn      = LWGEOM_mindistance2d,
       .distance3d_fn    = LWGEOM_mindistance3d
@@ -67,6 +73,8 @@ struct lwgeom_backend_definition lwgeom_backends[LWGEOM_NUM_BACKENDS] = {
       .intersects_fn    = sfcgal_intersects,
       .intersects3d_fn  = sfcgal_intersects3D,
       .intersection_fn  = sfcgal_intersection,
+      .difference_fn    = sfcgal_difference,
+      .union_fn         = sfcgal_union,
       .area_fn          = sfcgal_area,
       .distance_fn      = sfcgal_distance,
       .distance3d_fn    = sfcgal_distance3D
@@ -123,6 +131,18 @@ Datum intersection(PG_FUNCTION_ARGS)
     return (*lwgeom_backend->intersection_fn)( fcinfo );
 }
 
+PG_FUNCTION_INFO_V1(difference);
+Datum difference(PG_FUNCTION_ARGS)
+{
+    return (*lwgeom_backend->difference_fn)( fcinfo );
+}
+
+PG_FUNCTION_INFO_V1(geomunion);
+Datum geomunion(PG_FUNCTION_ARGS)
+{
+    return (*lwgeom_backend->union_fn)( fcinfo );
+}
+
 PG_FUNCTION_INFO_V1(area);
 Datum area(PG_FUNCTION_ARGS)
 {
index 9e5865c50f3e50eba0a02f4fea1276d15015a857..789030b287a8875c1eb0ae04393b75a7d6ce6f8e 100644 (file)
@@ -67,10 +67,10 @@ Datum buffer(PG_FUNCTION_ARGS);
 Datum geos_intersection(PG_FUNCTION_ARGS);
 Datum convexhull(PG_FUNCTION_ARGS);
 Datum topologypreservesimplify(PG_FUNCTION_ARGS);
-Datum difference(PG_FUNCTION_ARGS);
+Datum geos_difference(PG_FUNCTION_ARGS);
 Datum boundary(PG_FUNCTION_ARGS);
 Datum symdifference(PG_FUNCTION_ARGS);
-Datum geomunion(PG_FUNCTION_ARGS);
+Datum geos_geomunion(PG_FUNCTION_ARGS);
 Datum issimple(PG_FUNCTION_ARGS);
 Datum isring(PG_FUNCTION_ARGS);
 Datum pointonsurface(PG_FUNCTION_ARGS);
@@ -812,8 +812,8 @@ Datum ST_UnaryUnion(PG_FUNCTION_ARGS)
  * );
  *
  */
-PG_FUNCTION_INFO_V1(geomunion);
-Datum geomunion(PG_FUNCTION_ARGS)
+PG_FUNCTION_INFO_V1(geos_geomunion);
+Datum geos_geomunion(PG_FUNCTION_ARGS)
 {
        GSERIALIZED *geom1;
        GSERIALIZED *geom2;
@@ -1463,8 +1463,8 @@ Datum geos_intersection(PG_FUNCTION_ARGS)
  *      'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
  *     'POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))');
  */
-PG_FUNCTION_INFO_V1(difference);
-Datum difference(PG_FUNCTION_ARGS)
+PG_FUNCTION_INFO_V1(geos_difference);
+Datum geos_difference(PG_FUNCTION_ARGS)
 {
        GSERIALIZED *geom1;
        GSERIALIZED *geom2;
index 793b5ae6a72117a97510028dcd387c4b4e3cb3a0..5f9b8e45d67f63c834c06dee1eb8dea3a9c96671 100644 (file)
@@ -25,6 +25,8 @@ GEOSGeometry * POSTGIS2GEOS(GSERIALIZED *g);
 
 Datum geos_intersects(PG_FUNCTION_ARGS);
 Datum geos_intersection(PG_FUNCTION_ARGS);
+Datum geos_difference(PG_FUNCTION_ARGS);
+Datum geos_geomunion(PG_FUNCTION_ARGS);
 Datum LWGEOM_area_polygon(PG_FUNCTION_ARGS);
 Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS);
 Datum LWGEOM_mindistance3d(PG_FUNCTION_ARGS);
index 18243da2a3d9e21a335cdeca8191aec6a48fb4d0..1900c7011188c7e870813d4d4e5b3b87bb490dc7 100644 (file)
@@ -32,6 +32,11 @@ Datum sfcgal_intersects(PG_FUNCTION_ARGS);
 Datum sfcgal_intersects3D(PG_FUNCTION_ARGS);
 Datum sfcgal_intersection(PG_FUNCTION_ARGS);
 Datum sfcgal_intersection3D(PG_FUNCTION_ARGS);
+Datum sfcgal_difference(PG_FUNCTION_ARGS);
+Datum sfcgal_difference3D(PG_FUNCTION_ARGS);
+Datum sfcgal_union(PG_FUNCTION_ARGS);
+Datum sfcgal_union3D(PG_FUNCTION_ARGS);
+Datum sfcgal_volume(PG_FUNCTION_ARGS);
 Datum sfcgal_extrude(PG_FUNCTION_ARGS);
 Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS);
 Datum sfcgal_approximate_medial_axis(PG_FUNCTION_ARGS);
@@ -41,6 +46,8 @@ Datum sfcgal_force_lhr(PG_FUNCTION_ARGS);
 Datum sfcgal_triangulate(PG_FUNCTION_ARGS);
 Datum sfcgal_tesselate(PG_FUNCTION_ARGS);
 Datum sfcgal_minkowski_sum(PG_FUNCTION_ARGS);
+Datum sfcgal_make_solid(PG_FUNCTION_ARGS);
+Datum sfcgal_is_solid(PG_FUNCTION_ARGS);
 
 
 GSERIALIZED *geometry_serialize(LWGEOM *lwgeom);
@@ -506,6 +513,139 @@ Datum sfcgal_intersection3D(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(output);
 }
 
+PG_FUNCTION_INFO_V1(sfcgal_difference);        
+Datum sfcgal_difference(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *input0, *input1, *output;
+       sfcgal_geometry_t *geom0, *geom1;
+       sfcgal_geometry_t *result;
+       srid_t srid;
+
+       sfcgal_postgis_init();
+
+       input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       srid = gserialized_get_srid(input0);
+       input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+       geom0 = POSTGIS2SFCGALGeometry(input0);
+       PG_FREE_IF_COPY(input0, 0);
+       geom1 = POSTGIS2SFCGALGeometry(input1);
+       PG_FREE_IF_COPY(input1, 1);
+
+       result = sfcgal_geometry_difference(geom0, geom1);
+       sfcgal_geometry_delete(geom0);
+       sfcgal_geometry_delete(geom1);
+
+       output = SFCGALGeometry2POSTGIS(result, 0, srid);
+       sfcgal_geometry_delete(result);
+
+       PG_RETURN_POINTER(output);
+}
+
+
+PG_FUNCTION_INFO_V1(sfcgal_difference3D);      
+Datum sfcgal_difference3D(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *input0, *input1, *output;
+       sfcgal_geometry_t *geom0, *geom1;
+       sfcgal_geometry_t *result;
+       srid_t srid;
+
+       sfcgal_postgis_init();
+
+       input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       srid = gserialized_get_srid(input0);
+       input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+       geom0 = POSTGIS2SFCGALGeometry(input0);
+       PG_FREE_IF_COPY(input0, 0);
+       geom1 = POSTGIS2SFCGALGeometry(input1);
+       PG_FREE_IF_COPY(input1, 1);
+
+       result = sfcgal_geometry_difference_3d(geom0, geom1);
+       sfcgal_geometry_delete(geom0);
+       sfcgal_geometry_delete(geom1);
+
+       output = SFCGALGeometry2POSTGIS(result, 0, srid);
+       sfcgal_geometry_delete(result);
+
+       PG_RETURN_POINTER(output);
+}
+
+PG_FUNCTION_INFO_V1(sfcgal_union);     
+Datum sfcgal_union(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *input0, *input1, *output;
+       sfcgal_geometry_t *geom0, *geom1;
+       sfcgal_geometry_t *result;
+       srid_t srid;
+
+       sfcgal_postgis_init();
+
+       input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       srid = gserialized_get_srid(input0);
+       input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+       geom0 = POSTGIS2SFCGALGeometry(input0);
+       PG_FREE_IF_COPY(input0, 0);
+       geom1 = POSTGIS2SFCGALGeometry(input1);
+       PG_FREE_IF_COPY(input1, 1);
+
+       result = sfcgal_geometry_union(geom0, geom1);
+       sfcgal_geometry_delete(geom0);
+       sfcgal_geometry_delete(geom1);
+
+       output = SFCGALGeometry2POSTGIS(result, 0, srid);
+       sfcgal_geometry_delete(result);
+
+       PG_RETURN_POINTER(output);
+}
+
+
+PG_FUNCTION_INFO_V1(sfcgal_union3D);   
+Datum sfcgal_union3D(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *input0, *input1, *output;
+       sfcgal_geometry_t *geom0, *geom1;
+       sfcgal_geometry_t *result;
+       srid_t srid;
+
+       sfcgal_postgis_init();
+
+       input0 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       srid = gserialized_get_srid(input0);
+       input1 = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+       geom0 = POSTGIS2SFCGALGeometry(input0);
+       PG_FREE_IF_COPY(input0, 0);
+       geom1 = POSTGIS2SFCGALGeometry(input1);
+       PG_FREE_IF_COPY(input1, 1);
+
+       result = sfcgal_geometry_union_3d(geom0, geom1);
+       sfcgal_geometry_delete(geom0);
+       sfcgal_geometry_delete(geom1);
+
+       output = SFCGALGeometry2POSTGIS(result, 0, srid);
+       sfcgal_geometry_delete(result);
+
+       PG_RETURN_POINTER(output);
+}
+
+PG_FUNCTION_INFO_V1(sfcgal_volume);
+Datum sfcgal_volume(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *input;
+       sfcgal_geometry_t *geom;
+       double result;
+
+       sfcgal_postgis_init();
+
+       input = (GSERIALIZED*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       geom = POSTGIS2SFCGALGeometry(input);
+
+       result = sfcgal_geometry_volume(geom);
+       sfcgal_geometry_delete(geom);
+
+       PG_FREE_IF_COPY(input, 0);
+
+       PG_RETURN_FLOAT8(result);
+}
 
 PG_FUNCTION_INFO_V1(sfcgal_minkowski_sum);     
 Datum sfcgal_minkowski_sum(PG_FUNCTION_ARGS)
@@ -574,3 +714,41 @@ Datum postgis_sfcgal_version(PG_FUNCTION_ARGS)
         PG_RETURN_POINTER(result);
 }
 
+PG_FUNCTION_INFO_V1(sfcgal_is_solid);  
+Datum sfcgal_is_solid(PG_FUNCTION_ARGS)
+{
+       int result;
+       GSERIALIZED *input = PG_GETARG_GSERIALIZED_P(0);
+        LWGEOM *lwgeom = lwgeom_from_gserialized(input);
+       PG_FREE_IF_COPY(input, 0);
+       if (! lwgeom)
+       {
+               lwerror("sfcgal_is_solid: Unable to deserialize input");
+       }
+        result = FLAGS_GET_SOLID( lwgeom->flags );
+
+       lwgeom_free(lwgeom);
+
+       PG_RETURN_BOOL(result);
+}
+
+PG_FUNCTION_INFO_V1(sfcgal_make_solid);        
+Datum sfcgal_make_solid(PG_FUNCTION_ARGS)
+{
+        GSERIALIZED *output;
+       GSERIALIZED *input = PG_GETARG_GSERIALIZED_P(0);
+        LWGEOM *lwgeom = lwgeom_from_gserialized(input);
+       PG_FREE_IF_COPY(input, 0);
+       if (! lwgeom)
+       {
+               lwerror("sfcgal_make_solid: Unable to deserialize input");
+       }
+
+        FLAGS_SET_SOLID( lwgeom->flags, 1);
+
+       output = geometry_serialize( lwgeom );
+       lwgeom_free(lwgeom);
+
+       PG_RETURN_POINTER(output);
+}
+
index 52ad40a15dd354d39b9518188643acfeda633d23..067a277d8f5b1c4c4ac1b12c55e603b0ca01e7c4 100644 (file)
@@ -29,10 +29,17 @@ GSERIALIZED* SFCGALPreparedGeometry2POSTGIS( const sfcgal_prepared_geometry_t* g
 Datum sfcgal_intersects(PG_FUNCTION_ARGS);
 Datum sfcgal_intersects3D(PG_FUNCTION_ARGS);
 Datum sfcgal_intersection(PG_FUNCTION_ARGS);
+Datum sfcgal_difference3D(PG_FUNCTION_ARGS);
+Datum sfcgal_difference(PG_FUNCTION_ARGS);
+Datum sfcgal_union3D(PG_FUNCTION_ARGS);
+Datum sfcgal_union(PG_FUNCTION_ARGS);
+Datum sfcgal_volume(PG_FUNCTION_ARGS);
 Datum sfcgal_triangulate(PG_FUNCTION_ARGS);
 Datum sfcgal_area(PG_FUNCTION_ARGS);
 Datum sfcgal_distance(PG_FUNCTION_ARGS);
 Datum sfcgal_distance3D(PG_FUNCTION_ARGS);
+Datum sfcgal_make_solid(PG_FUNCTION_ARGS);
+Datum sfcgal_is_solid(PG_FUNCTION_ARGS);
 
 
 /* Initialize sfcgal with PostGIS error handlers */
index 89e291388f58489256007f37c2b34c2e0d88ff12..7b40dc2ebb12540b335fbc1a24400c55031b4f31 100644 (file)
@@ -29,6 +29,20 @@ CREATE OR REPLACE FUNCTION ST_3DIntersection(geom1 geometry, geom2 geometry)
        AS 'MODULE_PATHNAME','sfcgal_intersection3D'
        LANGUAGE 'c' IMMUTABLE STRICT
        COST 100;
+
+-- Availability: 2.2
+CREATE OR REPLACE FUNCTION ST_3DDifference(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','sfcgal_difference3D'
+       LANGUAGE 'c' IMMUTABLE STRICT
+       COST 100;
+       
+-- Availability: 2.2
+CREATE OR REPLACE FUNCTION ST_3DUnion(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','sfcgal_union3D'
+       LANGUAGE 'c' IMMUTABLE STRICT
+       COST 100;
        
 -- Availability: 2.1.0
 CREATE OR REPLACE FUNCTION ST_Tesselate(geometry)
@@ -116,4 +130,25 @@ CREATE OR REPLACE FUNCTION ST_IsPlanar(geometry)
        LANGUAGE 'c' IMMUTABLE STRICT
        COST 100;
 
+-- Availability: 2.2
+CREATE OR REPLACE FUNCTION ST_Volume(geometry)
+       RETURNS FLOAT8
+       AS 'MODULE_PATHNAME','sfcgal_volume'
+       LANGUAGE 'c' IMMUTABLE STRICT
+       COST 100;
+
+-- Availability: 2.2
+CREATE OR REPLACE FUNCTION ST_MakeSolid(geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','sfcgal_make_solid'
+       LANGUAGE 'c' IMMUTABLE STRICT
+       COST 100;
+
+-- Availability: 2.2
+CREATE OR REPLACE FUNCTION ST_IsSolid(geometry)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME','sfcgal_is_solid'
+       LANGUAGE 'c' IMMUTABLE STRICT
+       COST 100;
+
 COMMIT;
index 61992becf28a4d36cc9b1a880723275e81cb8734..2a4754834dc763ac9d80d5cee4655dfaf7061bfe 100644 (file)
@@ -2,9 +2,11 @@ SET postgis.backend = 'sfcgal';
 
 -- Tests to confirm the concave hull area is <= convex hull and 
 -- covers the original geometry (can't use covers because always gives topo errors with 3.3
+-- vmora: the small tolerance for area comes from the reordering of the geometry that
+--        cause small errors on area to cummulate (difference of 5e-13 on 2224 in this case)
 SELECT 
        'ST_ConcaveHull MultiPolygon 0.95', ST_Area(ST_Intersection(geom,ST_ConcaveHull(
-               geom, 0.95) )) = ST_Area(geom) As encloses_geom, 
+               geom, 0.95) )) - ST_Area(geom) < 1e-9 As encloses_geom, 
                (ST_Area(ST_ConvexHull(geom)) 
                - ST_Area(ST_ConcaveHull(geom, 0.95))) < (0.95 * ST_Area(ST_ConvexHull(geom) ) ) As reached_target
 FROM ST_Union(ST_GeomFromText('POLYGON((175 150, 20 40, 
index 0cb44f74e0ba62d92c8d7469466edf2010a93daa..758aaea342219d6fb7d781283b641f72ee7170c1 100644 (file)
@@ -42,7 +42,7 @@ WITH inp AS (SELECT
 WITH inp AS (SELECT
  'POLYGON EMPTY'::geometry as empty,
  'POLYGON((0 0, 10 0, 5 5, 0 0))'::geometry as geometry
- ) SELECT 'ST_Union(geometry, empty) == geometry', ST_AsEWKT(ST_Union(geometry, empty)) FROM inp;
+ ) SELECT 'ST_Union(geometry, empty) == geometry', ST_Equals(ST_ExteriorRing(ST_Union(geometry, empty)), 'LINESTRING(0 0, 10 0, 5 5, 0 0)'::geometry) FROM inp;
 WITH inp AS (SELECT
  'POLYGON EMPTY'::geometry as empty
  ) SELECT 'ST_Union(empty, empty) == empty', ST_IsEmpty(ST_Union(empty, empty)) FROM inp;
@@ -56,7 +56,7 @@ WITH inp AS (SELECT
 WITH inp AS (SELECT
  'POLYGON EMPTY'::geometry as empty,
  'POLYGON((0 0, 10 0, 5 5, 0 0))'::geometry as geometry
- ) SELECT 'ST_Difference(geometry, empty) == geometry', ST_AsEWKT(ST_Difference(geometry, empty)) FROM inp;
+ ) SELECT 'ST_Difference(geometry, empty) == geometry', ST_Equals(ST_ExteriorRing(ST_Difference(geometry, empty)),  'LINESTRING(0 0, 10 0, 5 5, 0 0)'::geometry) FROM inp;
 WITH inp AS (SELECT
  'POLYGON EMPTY'::geometry as empty,
  'POLYGON((0 0, 10 0, 5 5, 0 0))'::geometry as geometry
index cde19e329914371c38644bd84e2c6c46f2032431..866824a2308dabca20f0f91094b24f7706f11ce0 100644 (file)
@@ -24,11 +24,11 @@ T3.16|
 T3.17|
 T3.18|
 ST_Buffer(empty, tolerance) == empty|t
-ST_Union(geometry, empty) == geometry|POLYGON((0 0,10 0,5 5,0 0))
+ST_Union(geometry, empty) == geometry|t
 ST_Union(empty, empty) == empty|t
 ST_Intersection(geometry, empty) == geometry|t
 ST_Intersection(empty, empty) == empty|t
-ST_Difference(geometry, empty) == geometry|POLYGON((0 0,10 0,5 5,0 0))
+ST_Difference(geometry, empty) == geometry|t
 ST_Difference(empty, geometry) == empty|t
 ST_Distance(geometry, empty) == NULL|inf
 ST_DWithin(geometry, empty, tolerance) == FALSE|f
index cd05535d06c9fa14ba978375c1b0c3079b15b2c1..01cf20ce531a554c4b6acab0e0cb2469038cf756 100644 (file)
@@ -63,7 +63,7 @@ NOTICE:  Self-intersection
 isvalid|f
 isvalid|t
 intersection|POINT(-0 -0)
-difference|MULTILINESTRING((0 10,0 2),(0 -2,0 -10))
+difference|MULTILINESTRING((0 -2,0 -10),(0 10,0 2))
 boundary|MULTILINESTRING((0 0,0 10,10 10,10 0,0 0),(2 2,2 4,4 4,4 2,2 2))
 symdifference|GEOMETRYCOLLECTION(LINESTRING(2 2,4 4),LINESTRING(10 10,20 20),POLYGON((0 0,0 10,10 10,10 0,0 0),(4 4,2 4,2 2,4 2,4 4)))
 issimple|t