[postgis-tickets] r14786 - #3466, Casting from box3d to geometry drops Z dimension (Julien Rouhaud)

Daniel Baston dbaston at gmail.com
Mon Mar 14 18:09:00 PDT 2016


Author: dbaston
Date: 2016-03-14 18:08:59 -0700 (Mon, 14 Mar 2016)
New Revision: 14786

Modified:
   trunk/NEWS
   trunk/doc/introduction.xml
   trunk/liblwgeom/liblwgeom.h.in
   trunk/liblwgeom/lwpoly.c
   trunk/postgis/lwgeom_box.c
   trunk/postgis/lwgeom_box3d.c
   trunk/regress/regress.sql
   trunk/regress/regress_expected
   trunk/regress/sfcgal/regress.sql
   trunk/regress/sfcgal/regress_expected
Log:
#3466, Casting from box3d to geometry drops Z dimension (Julien Rouhaud)

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/NEWS	2016-03-15 01:08:59 UTC (rev 14786)
@@ -2,6 +2,8 @@
 2015/XX/XX
 
  * Important / Breaking Changes *
+  - #3466, Casting from box3d to geometry now returns a 3D
+	       geometry (Julien Rouhaud)
  * Deprecated signatures *
  * New Features *
 

Modified: trunk/doc/introduction.xml
===================================================================
--- trunk/doc/introduction.xml	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/doc/introduction.xml	2016-03-15 01:08:59 UTC (rev 14786)
@@ -208,6 +208,7 @@
 Jason Smith,
 Jeff Adams,
 Jose Carlos Martinez Llari,
+Julien Rouhaud,
 Kashif Rasul,
 Klaus Foerster,
 Kris Jurka,

Modified: trunk/liblwgeom/liblwgeom.h.in
===================================================================
--- trunk/liblwgeom/liblwgeom.h.in	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/liblwgeom/liblwgeom.h.in	2016-03-15 01:08:59 UTC (rev 14786)
@@ -1337,6 +1337,7 @@
 extern LWLINE *lwline_removepoint(LWLINE *line, uint32_t which);
 extern void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint);
 extern LWPOLY *lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes);
+extern LWPOLY* lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *p4);
 extern LWTRIANGLE *lwtriangle_from_lwline(const LWLINE *shell);
 extern LWMPOINT *lwmpoint_from_lwgeom(const LWGEOM *g); /* Extract the coordinates of an LWGEOM into an LWMPOINT */
 

Modified: trunk/liblwgeom/lwpoly.c
===================================================================
--- trunk/liblwgeom/lwpoly.c	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/liblwgeom/lwpoly.c	2016-03-15 01:08:59 UTC (rev 14786)
@@ -76,6 +76,24 @@
 }
 
 LWPOLY*
+lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2,
+		POINT4D *p3, POINT4D *p4)
+{
+	POINTARRAY *pa = ptarray_construct_empty(hasz, hasm, 5);
+	LWPOLY *lwpoly = lwpoly_construct_empty(SRID_UNKNOWN, hasz, hasm);
+
+	ptarray_append_point(pa, p1, LW_TRUE);
+	ptarray_append_point(pa, p2, LW_TRUE);
+	ptarray_append_point(pa, p3, LW_TRUE);
+	ptarray_append_point(pa, p4, LW_TRUE);
+	ptarray_append_point(pa, p1, LW_TRUE);
+
+	lwpoly_add_ring(lwpoly, pa);
+
+	return lwpoly;
+}
+
+LWPOLY*
 lwpoly_construct_empty(int srid, char hasz, char hasm)
 {
 	LWPOLY *result = lwalloc(sizeof(LWPOLY));

Modified: trunk/postgis/lwgeom_box.c
===================================================================
--- trunk/postgis/lwgeom_box.c	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/postgis/lwgeom_box.c	2016-03-15 01:08:59 UTC (rev 14786)
@@ -494,29 +494,18 @@
 	}
 	else
 	{
+		POINT4D points[4];
 		LWPOLY *poly;
-		POINTARRAY **ppa = lwalloc(sizeof(POINTARRAY*));
 
-		/* Assign coordinates to point array */
-		pt.x = box->xmin;
-		pt.y = box->ymin;
-		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = box->xmin;
-		pt.y = box->ymax;
-		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = box->xmax;
-		pt.y = box->ymax;
-		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = box->xmax;
-		pt.y = box->ymin;
-		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = box->xmin;
-		pt.y = box->ymin;
-		ptarray_append_point(pa, &pt, LW_TRUE);
+		/* Initialize the 4 vertices of the polygon */
+		points[0] = (POINT4D) { box->xmin, box->ymin };
+		points[1] = (POINT4D) { box->xmin, box->ymax };
+		points[2] = (POINT4D) { box->xmax, box->ymax };
+		points[3] = (POINT4D) { box->xmax, box->ymin };
 
 		/* Construct polygon */
-		ppa[0] = pa;
-		poly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, ppa);
+		poly = lwpoly_construct_rectangle(LW_FALSE, LW_FALSE, &points[0], &points[1],
+				&points[2], &points[3]);
 		result = geometry_serialize(lwpoly_as_lwgeom(poly));
 		lwpoly_free(poly);
 	}

Modified: trunk/postgis/lwgeom_box3d.c
===================================================================
--- trunk/postgis/lwgeom_box3d.c	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/postgis/lwgeom_box3d.c	2016-03-15 01:08:59 UTC (rev 14786)
@@ -199,69 +199,159 @@
 	GSERIALIZED *result;
 	POINT4D pt;
 
-
 	/**
 	 * Alter BOX3D cast so that a valid geometry is always
 	 * returned depending upon the size of the BOX3D. The
 	 * code makes the following assumptions:
 	 *     - If the BOX3D is a single point then return a
 	 *     POINT geometry
-	 *     - If the BOX3D represents either a horizontal or
-	 *     vertical line, return a LINESTRING geometry
-	 *     - Otherwise return a POLYGON
+	 *     - If the BOX3D represents a line in any of X, Y
+	 *     or Z dimension, return a LINESTRING geometry
+	 *     - If the BOX3D represents a plane in the X, Y,
+	 *     or Z dimension, return a POLYGON geometry
+	 *     - Otherwise return a POLYHEDRALSURFACE geometry
 	 */
 
-	pa = ptarray_construct_empty(0, 0, 5);
+	pa = ptarray_construct_empty(LW_TRUE, LW_FALSE, 5);
 
-	if ( (box->xmin == box->xmax) && (box->ymin == box->ymax) )
+	/* BOX3D is a point */
+	if ( (box->xmin == box->xmax) && (box->ymin == box->ymax) &&
+			(box->zmin == box->zmax) )
 	{
 		LWPOINT *lwpt = lwpoint_construct(SRID_UNKNOWN, NULL, pa);
 
 		pt.x = box->xmin;
 		pt.y = box->ymin;
+		pt.z = box->zmin;
 		ptarray_append_point(pa, &pt, LW_TRUE);
 
 		result = geometry_serialize(lwpoint_as_lwgeom(lwpt));
+		lwpoint_free(lwpt);
 	}
-	else if (box->xmin == box->xmax ||
-	         box->ymin == box->ymax)
+	/* BOX3D is a line */
+	else if (((box->xmin == box->xmax ||
+			   box->ymin == box->ymax) &&
+			   box->zmin == box->zmax) ||
+		     ((box->xmin == box->xmax ||
+			   box->zmin == box->zmax) &&
+			   box->ymin == box->ymax) ||
+		     ((box->ymin == box->ymax ||
+			   box->zmin == box->zmax) &&
+			   box->xmin == box->xmax))
 	{
 		LWLINE *lwline = lwline_construct(SRID_UNKNOWN, NULL, pa);
 
 		pt.x = box->xmin;
 		pt.y = box->ymin;
+		pt.z = box->zmin;
 		ptarray_append_point(pa, &pt, LW_TRUE);
 		pt.x = box->xmax;
 		pt.y = box->ymax;
+		pt.z = box->zmax;
 		ptarray_append_point(pa, &pt, LW_TRUE);
 
 		result = geometry_serialize(lwline_as_lwgeom(lwline));
+		lwline_free(lwline);
 	}
-	else
+	/* BOX3D is a polygon in the X plane */
+	else if (box->xmin == box->xmax)
 	{
-		LWPOLY *lwpoly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, &pa);
+		POINT4D points[4];
+		LWPOLY *lwpoly;
 
-		pt.x = box->xmin;
-		pt.y = box->ymin;
-		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = box->xmin;
-		pt.y = box->ymax;
-		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = box->xmax;
-		pt.y = box->ymax;
-		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = box->xmax;
-		pt.y = box->ymin;
-		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = box->xmin;
-		pt.y = box->ymin;
-		ptarray_append_point(pa, &pt, LW_TRUE);
+		/* Initialize the 4 vertices of the polygon */
+		points[0] = (POINT4D) { box->xmin, box->ymin, box->zmin };
+		points[1] = (POINT4D) { box->xmin, box->ymax, box->zmin };
+		points[2] = (POINT4D) { box->xmin, box->ymax, box->zmax };
+		points[3] = (POINT4D) { box->xmin, box->ymin, box->zmax };
 
+		lwpoly = lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, 
+				&points[0], &points[1], &points[2], &points[3]);
 		result = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
-		
+		lwpoly_free(lwpoly);
 	}
+	/* BOX3D is a polygon in the Y plane */
+	else if (box->ymin == box->ymax)
+	{
+		POINT4D points[4];
+		LWPOLY *lwpoly;
 
+		/* Initialize the 4 vertices of the polygon */
+		points[0] = (POINT4D) { box->xmin, box->ymin, box->zmin };
+		points[1] = (POINT4D) { box->xmax, box->ymin, box->zmin };
+		points[2] = (POINT4D) { box->xmax, box->ymin, box->zmax };
+		points[3] = (POINT4D) { box->xmin, box->ymin, box->zmax };
+
+		lwpoly = lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, 
+				&points[0], &points[1], &points[2], &points[3]);
+		result = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
+		lwpoly_free(lwpoly);
+	}
+	/* BOX3D is a polygon in the Z plane */
+	else if (box->zmin == box->zmax)
+	{
+		POINT4D points[4];
+		LWPOLY *lwpoly;
+
+		/* Initialize the 4 vertices of the polygon */
+		points[0] = (POINT4D) { box->xmin, box->ymin, box->zmin };
+		points[1] = (POINT4D) { box->xmin, box->ymax, box->zmin };
+		points[2] = (POINT4D) { box->xmax, box->ymax, box->zmin };
+		points[3] = (POINT4D) { box->xmax, box->ymin, box->zmin };
+
+		lwpoly = lwpoly_construct_rectangle(LW_TRUE, LW_FALSE,
+			   	&points[0], &points[1], &points[2], &points[3]);
+		result = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
+		lwpoly_free(lwpoly);
+	}
+	/* BOX3D is a polyhedron */
+	else
+	{
+		POINT4D points[8];
+		static const int ngeoms = 6;
+		LWGEOM **geoms = (LWGEOM **) lwalloc(sizeof(LWGEOM *) * ngeoms);
+		LWGEOM *geom = NULL;
+
+		/* Initialize the 8 vertices of the box */
+		points[0] = (POINT4D) { box->xmin, box->ymin, box->zmin };
+		points[1] = (POINT4D) { box->xmin, box->ymax, box->zmin };
+		points[2] = (POINT4D) { box->xmax, box->ymax, box->zmin };
+		points[3] = (POINT4D) { box->xmax, box->ymin, box->zmin };
+		points[4] = (POINT4D) { box->xmin, box->ymin, box->zmax };
+		points[5] = (POINT4D) { box->xmin, box->ymax, box->zmax };
+		points[6] = (POINT4D) { box->xmax, box->ymax, box->zmax };
+		points[7] = (POINT4D) { box->xmax, box->ymin, box->zmax };
+
+		/* add bottom polygon */
+		geoms[0] = lwpoly_as_lwgeom(lwpoly_construct_rectangle(LW_TRUE, LW_FALSE,
+				   	&points[0], &points[1], &points[2], &points[3]));
+		/* add top polygon */
+		geoms[1] = lwpoly_as_lwgeom(lwpoly_construct_rectangle(LW_TRUE, LW_FALSE,
+				   	&points[4], &points[5], &points[6], &points[7]));
+		/* add left polygon */
+		geoms[2] = lwpoly_as_lwgeom(lwpoly_construct_rectangle(LW_TRUE, LW_FALSE,
+				   	&points[0], &points[1], &points[5], &points[4]));
+		/* add right polygon */
+		geoms[3] = lwpoly_as_lwgeom(lwpoly_construct_rectangle(LW_TRUE, LW_FALSE,
+				   	&points[3], &points[2], &points[6], &points[7]));
+		/* add back polygon */
+		geoms[4] = lwpoly_as_lwgeom(lwpoly_construct_rectangle(LW_TRUE, LW_FALSE,
+				   	&points[0], &points[3], &points[7], &points[4]));
+		/* add front polygon */
+		geoms[5] = lwpoly_as_lwgeom(lwpoly_construct_rectangle(LW_TRUE, LW_FALSE,
+				   	&points[1], &points[2], &points[6], &points[5]));
+
+		geom = (LWGEOM *) lwcollection_construct(POLYHEDRALSURFACETYPE,
+				SRID_UNKNOWN, NULL, ngeoms, geoms);
+
+		FLAGS_SET_SOLID(geom->flags, 1);
+
+		result = geometry_serialize(geom);
+		lwcollection_free((LWCOLLECTION *) geom);
+	}
+
 	gserialized_set_srid(result, box->srid);
+
 	PG_RETURN_POINTER(result);
 }
 

Modified: trunk/regress/regress.sql
===================================================================
--- trunk/regress/regress.sql	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/regress/regress.sql	2016-03-15 01:08:59 UTC (rev 14786)
@@ -1,3 +1,4 @@
+-- postgres
 --- regression test for postGIS
 
 
@@ -129,7 +130,12 @@
 select '106',box3d('MULTIPOINT(0 0, 7 7)'::GEOMETRY) as bvol;
 
 -- box3d only type is only used for indexing -- NEVER use one yourself
-select '107',ST_AsEWKT(geometry('BOX3D(0 0 0, 7 7 7 )'::BOX3D));
+select '107a',ST_AsEWKT(geometry('BOX3D(1 2 3, 1 2 3 )'::BOX3D));
+select '107b',ST_AsEWKT(geometry('BOX3D(2 3 3, 7 3 3 )'::BOX3D));
+select '107c',ST_AsEWKT(geometry('BOX3D(2 3 5, 6 8 5 )'::BOX3D));
+select '107d',ST_AsEWKT(geometry('BOX3D(1 -1 4, 2 -1 9 )'::BOX3D));
+select '107e',ST_AsEWKT(geometry('BOX3D(-1 3 5, -1 6 8 )'::BOX3D));
+select '107f',ST_AsEWKT(geometry('BOX3D(1 2 3, 4 5 6 )'::BOX3D));
 
 --- debug function testing
 

Modified: trunk/regress/regress_expected
===================================================================
--- trunk/regress/regress_expected	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/regress/regress_expected	2016-03-15 01:08:59 UTC (rev 14786)
@@ -87,7 +87,12 @@
 76|f
 76a|f
 106|BOX3D(0 0 0,7 7 0)
-107|POLYGON((0 0,0 7,7 7,7 0,0 0))
+107a|POINT(1 2 3)
+107b|LINESTRING(2 3 3,7 3 3)
+107c|POLYGON((2 3 5,2 8 5,6 8 5,6 3 5,2 3 5))
+107d|POLYGON((1 -1 4,2 -1 4,2 -1 9,1 -1 9,1 -1 4))
+107e|POLYGON((-1 3 5,-1 6 5,-1 6 8,-1 3 8,-1 3 5))
+107f|POLYHEDRALSURFACE(((1 2 3,1 5 3,4 5 3,4 2 3,1 2 3)),((1 2 6,1 5 6,4 5 6,4 2 6,1 2 6)),((1 2 3,1 5 3,1 5 6,1 2 6,1 2 3)),((4 2 3,4 5 3,4 5 6,4 2 6,4 2 3)),((1 2 3,4 2 3,4 2 6,1 2 6,1 2 3)),((1 5 3,4 5 3,4 5 6,1 5 6,1 5 3)))
 108|2
 109|4
 110|6

Modified: trunk/regress/sfcgal/regress.sql
===================================================================
--- trunk/regress/sfcgal/regress.sql	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/regress/sfcgal/regress.sql	2016-03-15 01:08:59 UTC (rev 14786)
@@ -178,7 +178,12 @@
 select '106',box3d('MULTIPOINT(0 0, 7 7)'::GEOMETRY) as bvol;
 
 -- box3d only type is only used for indexing -- NEVER use one yourself
-select '107',ST_AsEWKT(geometry('BOX3D(0 0 0, 7 7 7 )'::BOX3D));
+select '107a',ST_AsEWKT(geometry('BOX3D(1 2 3, 1 2 3 )'::BOX3D));
+select '107b',ST_AsEWKT(geometry('BOX3D(2 3 3, 7 3 3 )'::BOX3D));
+select '107c',ST_AsEWKT(geometry('BOX3D(2 3 5, 6 8 5 )'::BOX3D));
+select '107d',ST_AsEWKT(geometry('BOX3D(1 -1 4, 2 -1 9 )'::BOX3D));
+select '107e',ST_AsEWKT(geometry('BOX3D(-1 3 5, -1 6 8 )'::BOX3D));
+select '107f',ST_AsEWKT(geometry('BOX3D(1 2 3, 4 5 6 )'::BOX3D));
 
 --- debug function testing
 

Modified: trunk/regress/sfcgal/regress_expected
===================================================================
--- trunk/regress/sfcgal/regress_expected	2016-03-13 22:25:39 UTC (rev 14785)
+++ trunk/regress/sfcgal/regress_expected	2016-03-15 01:08:59 UTC (rev 14786)
@@ -116,7 +116,12 @@
 104|t
 105|f
 106|BOX3D(0 0 0,7 7 0)
-107|POLYGON((0 0,0 7,7 7,7 0,0 0))
+107a|POINT(1 2 3)
+107b|LINESTRING(2 3 3,7 3 3)
+107c|POLYGON((2 3 5,2 8 5,6 8 5,6 3 5,2 3 5))
+107d|POLYGON((1 -1 4,2 -1 4,2 -1 9,1 -1 9,1 -1 4))
+107e|POLYGON((-1 3 5,-1 6 5,-1 6 8,-1 3 8,-1 3 5))
+107f|POLYHEDRALSURFACE(((1 2 3,1 5 3,4 5 3,4 2 3,1 2 3)),((1 2 6,1 5 6,4 5 6,4 2 6,1 2 6)),((1 2 3,1 5 3,1 5 6,1 2 6,1 2 3)),((4 2 3,4 5 3,4 5 6,4 2 6,4 2 3)),((1 2 3,4 2 3,4 2 6,1 2 6,1 2 3)),((1 5 3,4 5 3,4 5 6,1 5 6,1 5 3)))
 108|2
 109|4
 110|6



More information about the postgis-tickets mailing list