[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