#3466, Casting from box3d to geometry drops Z dimension (Julien Rouhaud)

git-svn-id: http://svn.osgeo.org/postgis/trunk@14786 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
Daniel Baston 2016-03-15 01:08:59 +00:00
parent 59a06fcf53
commit 45b0803360
10 changed files with 171 additions and 49 deletions

2
NEWS
View file

@ -2,6 +2,8 @@ PostGIS 2.3.0
2015/XX/XX
* Important / Breaking Changes *
- #3466, Casting from box3d to geometry now returns a 3D
geometry (Julien Rouhaud)
* Deprecated signatures *
* New Features *

View file

@ -208,6 +208,7 @@ Ingvild Nystuen,
Jason Smith,
Jeff Adams,
Jose Carlos Martinez Llari,
Julien Rouhaud,
Kashif Rasul,
Klaus Foerster,
Kris Jurka,

View file

@ -1337,6 +1337,7 @@ extern LWLINE *lwline_addpoint(LWLINE *line, LWPOINT *point, uint32_t where);
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 */

View file

@ -75,6 +75,24 @@ lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
return result;
}
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)
{

View file

@ -494,29 +494,18 @@ Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS)
}
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);
}

View file

@ -199,69 +199,159 @@ Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS)
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);
}
/* BOX3D is a polygon in the X plane */
else if (box->xmin == box->xmax)
{
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->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
{
LWPOLY *lwpoly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, &pa);
POINT4D points[8];
static const int ngeoms = 6;
LWGEOM **geoms = (LWGEOM **) lwalloc(sizeof(LWGEOM *) * ngeoms);
LWGEOM *geom = NULL;
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 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 };
result = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
/* 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);
}

View file

@ -1,3 +1,4 @@
-- postgres
--- regression test for postGIS
@ -129,7 +130,12 @@ select '76a',ST_OrderingEquals('LINESTRING(1 1, 2 2)'::GEOMETRY,'LINESTRING(1 1,
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

View file

@ -87,7 +87,12 @@ ERROR: parse error - invalid geometry at character 23
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

View file

@ -178,7 +178,12 @@ select '105','MULTIPOINT(-0.0001 0, 7 7)'::GEOMETRY @ 'MULTIPOINT(0 0, 10 10)'::
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

View file

@ -116,7 +116,12 @@ ERROR: parse error - invalid geometry at character 23
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