2010-08-30 06:49:51 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* $Id:$
|
|
|
|
*
|
|
|
|
* PostGIS - Spatial Types for PostgreSQL
|
|
|
|
* http://postgis.refractions.net
|
|
|
|
* Copyright 2010 Olivier Courtin <olivier.courtin@oslandia.com>
|
|
|
|
*
|
|
|
|
* This is free software; you can redistribute and/or modify it under
|
|
|
|
* the terms of the GNU General Public Licence. See the COPYING file.
|
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
2010-10-31 02:31:34 +00:00
|
|
|
#include "liblwgeom_internal.h"
|
2010-08-30 06:49:51 +00:00
|
|
|
#include "libtgeom.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a new empty tgeom struct
|
|
|
|
* Return a pointer on the newly allocated struct
|
|
|
|
*/
|
|
|
|
TGEOM*
|
2010-11-21 19:02:23 +00:00
|
|
|
tgeom_new(uchar type, int hasz, int hasm)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
TGEOM *tgeom;
|
|
|
|
|
|
|
|
tgeom = lwalloc(sizeof(TGEOM));
|
|
|
|
tgeom->type = type;
|
2010-11-21 19:02:23 +00:00
|
|
|
FLAGS_SET_Z(tgeom->flags, hasz);
|
|
|
|
FLAGS_SET_M(tgeom->flags, hasm);
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom->bbox=NULL;
|
|
|
|
tgeom->srid=0;
|
|
|
|
tgeom->nedges=0;
|
|
|
|
tgeom->maxedges=0;
|
|
|
|
tgeom->edges=NULL;
|
|
|
|
tgeom->maxfaces=0;
|
|
|
|
tgeom->nfaces=0;
|
|
|
|
tgeom->faces=NULL;
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
return tgeom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if a edge (start and end points) are or not already
|
|
|
|
* in a given tgeom.
|
|
|
|
* Return 0 if not in.
|
|
|
|
* Return positive index edge number if the edge is well oriented
|
2010-08-30 09:06:40 +00:00
|
|
|
* Return negative index edge number if the edge is reversed
|
2010-08-30 06:49:51 +00:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
tgeom_is_edge(const TGEOM *tgeom, const POINT4D *s, const POINT4D *e)
|
|
|
|
{
|
|
|
|
int i, hasz, hasm;
|
|
|
|
POINT4D *p1, *p2;
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
assert(s);
|
|
|
|
assert(e);
|
|
|
|
|
|
|
|
hasz = FLAGS_GET_Z(tgeom->flags);
|
|
|
|
hasm = FLAGS_GET_M(tgeom->flags);
|
|
|
|
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "To check [%lf,%lf,%lf,%lf] -> [%lf,%lf,%lf,%lf]\n",
|
2010-08-30 09:06:40 +00:00
|
|
|
s->x, s->y, s->z, s->m, e->x, e->y, e->z, e->m);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
for (i=1 ; i <= tgeom->nedges ; i++) /* edges are 1 based */
|
|
|
|
{
|
|
|
|
p1 = tgeom->edges[i]->s;
|
|
|
|
p2 = tgeom->edges[i]->e;
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "[%i]/[%i] (%lf,%lf,%lf,%lf) -> (%lf,%lf,%lf,%lf)\n",
|
|
|
|
i, tgeom->nedges,
|
2010-09-05 15:25:50 +00:00
|
|
|
p1->x, p1->y, p1->z, p1->m,
|
|
|
|
p2->x, p2->y, p2->z, p2->m);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* X,Y,Z,M */
|
|
|
|
if (hasz && hasm)
|
|
|
|
{
|
|
|
|
if ( p1->x == e->x && p1->y == e->y && p1->z == e->z && p1->m == e->m &&
|
2010-08-30 09:06:40 +00:00
|
|
|
p2->x == s->x && p2->y == s->y && p2->z == s->z && p2->m == s->m)
|
2010-08-30 06:49:51 +00:00
|
|
|
return -i;
|
|
|
|
|
|
|
|
if ( p1->x == s->x && p1->y == s->y && p1->z == s->z && p1->m == s->m &&
|
2010-08-30 09:06:40 +00:00
|
|
|
p2->x == e->x && p2->y == e->y && p2->z == e->z && p2->m == e->m)
|
2010-08-30 06:49:51 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
/* X,Y,Z */
|
|
|
|
else if (hasz && !hasm)
|
|
|
|
{
|
|
|
|
if ( p1->x == e->x && p1->y == e->y && p1->z == e->z &&
|
2010-08-30 09:06:40 +00:00
|
|
|
p2->x == s->x && p2->y == s->y && p2->z == s->z )
|
2010-08-30 06:49:51 +00:00
|
|
|
return -i;
|
|
|
|
|
|
|
|
if ( p1->x == s->x && p1->y == s->y && p1->z == s->z &&
|
2010-08-30 09:06:40 +00:00
|
|
|
p2->x == e->x && p2->y == e->y && p2->z == e->z )
|
2010-08-30 06:49:51 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
/* X,Y,M */
|
|
|
|
else if (!hasz && hasm)
|
|
|
|
{
|
|
|
|
if ( p1->x == e->x && p1->y == e->y && p1->m == e->m &&
|
2010-08-30 09:06:40 +00:00
|
|
|
p2->x == s->x && p2->y == s->y && p2->m == s->m )
|
2010-08-30 06:49:51 +00:00
|
|
|
return -i;
|
|
|
|
|
|
|
|
if ( p1->x == s->x && p1->y == s->y && p1->m == s->m &&
|
2010-08-30 09:06:40 +00:00
|
|
|
p2->x == e->x && p2->y == e->y && p2->m == e->m )
|
2010-08-30 06:49:51 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
else /*X,Y */
|
|
|
|
{
|
|
|
|
if ( p1->x == e->x && p1->y == e->y &&
|
2010-08-30 09:06:40 +00:00
|
|
|
p2->x == s->x && p2->y == s->y)
|
2010-08-30 06:49:51 +00:00
|
|
|
return -i;
|
|
|
|
|
|
|
|
if ( p1->x == s->x && p1->y == s->y &&
|
2010-08-30 09:06:40 +00:00
|
|
|
p2->x == e->x && p2->y == e->y)
|
2010-08-30 06:49:51 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUG(3, "Edge not found in array");
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
return 0;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2010-08-30 09:06:40 +00:00
|
|
|
* Add an edge to a face in a tgeom
|
2010-08-30 06:49:51 +00:00
|
|
|
* Edge is describded as a starting and an ending point
|
2010-08-30 09:06:40 +00:00
|
|
|
* Points are really copied
|
2010-08-30 06:49:51 +00:00
|
|
|
* Return the new tgeom pointer
|
|
|
|
*/
|
|
|
|
static TGEOM*
|
|
|
|
tgeom_add_face_edge(TGEOM *tgeom, int face_id, POINT4D *s, POINT4D *e)
|
|
|
|
{
|
|
|
|
int nedges, edge_id;
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
assert(s);
|
|
|
|
assert(e);
|
|
|
|
|
|
|
|
edge_id = tgeom_is_edge(tgeom, s, e);
|
|
|
|
|
|
|
|
if (edge_id)
|
|
|
|
{
|
|
|
|
tgeom->edges[abs(edge_id)]->count++;
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "face [%i] Founded Edge: %i\n",
|
2010-08-30 09:06:40 +00:00
|
|
|
face_id, edge_id);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((tgeom->nedges + 1) == INT_MAX)
|
|
|
|
lwerror("tgeom_add_face_edge: Unable to alloc more than %i edges", INT_MAX);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* alloc edges array */
|
|
|
|
if (tgeom->maxedges == 0)
|
|
|
|
{
|
2010-09-10 14:06:11 +00:00
|
|
|
tgeom->edges = (TEDGE**) lwalloc(sizeof(TEDGE*) * 4);
|
2010-08-30 09:06:40 +00:00
|
|
|
tgeom->maxedges = 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
if (tgeom->maxedges >= (tgeom->nedges + 1))
|
|
|
|
{
|
2010-09-10 14:06:11 +00:00
|
|
|
tgeom->edges = (TEDGE **) lwrealloc(tgeom->edges,
|
|
|
|
sizeof(TEDGE*) * tgeom->maxedges * 2);
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom->maxedges *= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
edge_id = ++tgeom->nedges; /* edge_id is 1 based */
|
2010-09-10 14:06:11 +00:00
|
|
|
tgeom->edges[edge_id] = (TEDGE*) lwalloc(sizeof(TEDGE));
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom->edges[edge_id]->s = lwalloc(sizeof(POINT4D));
|
|
|
|
tgeom->edges[edge_id]->e = lwalloc(sizeof(POINT4D));
|
|
|
|
memcpy(tgeom->edges[edge_id]->s, s, sizeof(POINT4D));
|
|
|
|
memcpy(tgeom->edges[edge_id]->e, e, sizeof(POINT4D));
|
|
|
|
tgeom->edges[edge_id]->count = 1;
|
|
|
|
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "face [%i] adding edge [%i] (%lf, %lf, %lf, %lf) -> (%lf, %lf, %lf, %lf)\n",
|
2010-08-30 09:06:40 +00:00
|
|
|
face_id, edge_id, s->x, s->y, s->z, s->m, e->x, e->y, e->z, e->m);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nedges = tgeom->faces[face_id]->nedges;
|
2010-08-30 09:06:40 +00:00
|
|
|
if (tgeom->faces[face_id]->maxedges == 0)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-09-10 14:06:11 +00:00
|
|
|
tgeom->faces[face_id]->edges = (int *) lwalloc(sizeof(int) * 4);
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom->faces[face_id]->maxedges = 4;
|
|
|
|
}
|
2010-08-30 09:06:40 +00:00
|
|
|
if (tgeom->faces[face_id]->maxedges == nedges)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-09-10 14:06:11 +00:00
|
|
|
tgeom->faces[face_id]->edges = (int *) lwrealloc(tgeom->faces[face_id]->edges,
|
|
|
|
sizeof(int) * tgeom->faces[face_id]->maxedges * 2);
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom->faces[face_id]->maxedges *= 2;
|
|
|
|
}
|
|
|
|
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "face [%i] add %i in edge array in %i pos\n",
|
2010-08-30 09:06:40 +00:00
|
|
|
face_id, edge_id, tgeom->faces[face_id]->nedges);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
tgeom->faces[face_id]->edges[nedges]= edge_id;
|
|
|
|
tgeom->faces[face_id]->nedges++;
|
|
|
|
|
|
|
|
return tgeom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2010-08-30 09:06:40 +00:00
|
|
|
* Add a LWPOLY inside a tgeom
|
2010-08-30 06:49:51 +00:00
|
|
|
* Copy geometries from LWPOLY
|
|
|
|
*/
|
|
|
|
static TGEOM*
|
|
|
|
tgeom_add_polygon(TGEOM *tgeom, LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
assert(poly);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
if ((tgeom->nfaces + 1) == INT_MAX)
|
|
|
|
lwerror("tgeom_add_polygon: Unable to alloc more than %i faces", INT_MAX);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* Integrity checks on subgeom, dims and srid */
|
|
|
|
if (tgeom->type != POLYHEDRALSURFACETYPE)
|
|
|
|
lwerror("tgeom_add_polygon: Unable to handle %s - %s type",
|
2010-08-30 09:06:40 +00:00
|
|
|
tgeom->type, lwtype_name(tgeom->type));
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
if (FLAGS_NDIMS(tgeom->flags) != FLAGS_NDIMS(poly->flags))
|
2010-08-30 06:49:51 +00:00
|
|
|
lwerror("tgeom_add_polygon: Mixed dimension");
|
|
|
|
|
2010-12-07 21:59:54 +00:00
|
|
|
if (tgeom->srid != poly->srid && (tgeom->srid != 0 && poly->srid != SRID_UNKNOWN))
|
2010-08-30 06:49:51 +00:00
|
|
|
lwerror("tgeom_add_polygon: Mixed srid. Tgeom: %i / Polygon: %i",
|
2010-11-25 17:34:21 +00:00
|
|
|
tgeom->srid, poly->srid);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* handle face array allocation */
|
|
|
|
if (tgeom->maxfaces == 0)
|
|
|
|
{
|
|
|
|
tgeom->faces = lwalloc(sizeof(TFACE*) * 2);
|
|
|
|
tgeom->maxfaces = 2;
|
|
|
|
}
|
|
|
|
if ((tgeom->maxfaces - 1) == tgeom->nfaces)
|
|
|
|
{
|
|
|
|
tgeom->faces = lwrealloc(tgeom->faces,
|
2010-08-30 09:06:40 +00:00
|
|
|
sizeof(TFACE*) * tgeom->maxfaces * 2);
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom->maxfaces *= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add an empty face */
|
|
|
|
tgeom->faces[tgeom->nfaces] = lwalloc(sizeof(TFACE));
|
|
|
|
tgeom->faces[tgeom->nfaces]->rings = NULL;
|
|
|
|
tgeom->faces[tgeom->nfaces]->nrings = 0;
|
|
|
|
tgeom->faces[tgeom->nfaces]->nedges = 0;
|
|
|
|
tgeom->faces[tgeom->nfaces]->maxedges = 0;
|
|
|
|
|
|
|
|
/* Compute edge on poly external ring */
|
|
|
|
for (i=1 ; i < poly->rings[0]->npoints ; i++)
|
|
|
|
{
|
|
|
|
POINT4D p1, p2;
|
|
|
|
|
|
|
|
getPoint4d_p(poly->rings[0], i-1, &p1);
|
|
|
|
getPoint4d_p(poly->rings[0], i, &p2);
|
|
|
|
tgeom_add_face_edge(tgeom, tgeom->nfaces, &p1, &p2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* External ring is already handled by edges */
|
|
|
|
tgeom->faces[tgeom->nfaces]->nrings = poly->nrings - 1;
|
|
|
|
|
|
|
|
/* handle rings array allocation */
|
|
|
|
if (tgeom->faces[tgeom->nfaces]->nrings >= 1)
|
|
|
|
tgeom->faces[tgeom->nfaces]->rings = lwalloc(sizeof(POINTARRAY*)
|
2010-08-30 09:06:40 +00:00
|
|
|
* tgeom->faces[tgeom->nfaces]->nrings);
|
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* clone internal rings */
|
2010-08-30 09:06:40 +00:00
|
|
|
for (i=0 ; i < tgeom->faces[tgeom->nfaces]->nrings ; i++)
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom->faces[tgeom->nfaces]->rings[i]
|
2010-08-30 09:06:40 +00:00
|
|
|
= ptarray_clone(poly->rings[i+1]);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
tgeom->nfaces++;
|
|
|
|
|
|
|
|
return tgeom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2010-08-30 09:06:40 +00:00
|
|
|
* Add a LWTRIANGLE inside a tgeom
|
2010-08-30 06:49:51 +00:00
|
|
|
* Copy geometries from LWTRIANGLE
|
|
|
|
*/
|
|
|
|
static TGEOM*
|
|
|
|
tgeom_add_triangle(TGEOM *tgeom, LWTRIANGLE *triangle)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
assert(triangle);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
if ((tgeom->nfaces + 1) == INT_MAX)
|
|
|
|
lwerror("tgeom_add_triangle: Unable to alloc more than %i faces", INT_MAX);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* Integrity checks on subgeom, dims and srid */
|
|
|
|
if (tgeom->type != TINTYPE)
|
|
|
|
lwerror("tgeom_add_triangle: Unable to handle %s - %s type",
|
2010-08-30 09:06:40 +00:00
|
|
|
tgeom->type, lwtype_name(tgeom->type));
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
if (FLAGS_NDIMS(tgeom->flags) != FLAGS_NDIMS(triangle->flags))
|
2010-08-30 06:49:51 +00:00
|
|
|
lwerror("tgeom_add_triangle: Mixed dimension");
|
|
|
|
|
2010-11-25 17:34:21 +00:00
|
|
|
if (tgeom->srid != triangle->srid
|
2010-12-07 21:59:54 +00:00
|
|
|
&& (tgeom->srid != 0 && triangle->srid != SRID_UNKNOWN))
|
2010-08-30 06:49:51 +00:00
|
|
|
lwerror("tgeom_add_triangle: Mixed srid. Tgeom: %i / Triangle: %i",
|
2010-11-25 17:34:21 +00:00
|
|
|
tgeom->srid, triangle->srid);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* handle face array allocation */
|
|
|
|
if (tgeom->maxfaces == 0)
|
|
|
|
{
|
|
|
|
tgeom->faces = lwalloc(sizeof(TFACE*) * 2);
|
|
|
|
tgeom->maxfaces = 2;
|
|
|
|
}
|
|
|
|
if ((tgeom->maxfaces - 1) == tgeom->nfaces)
|
|
|
|
{
|
|
|
|
tgeom->faces = lwrealloc(tgeom->faces,
|
2010-08-30 09:06:40 +00:00
|
|
|
sizeof(TFACE*) * tgeom->maxfaces * 2);
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom->maxfaces *= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add an empty face */
|
|
|
|
tgeom->faces[tgeom->nfaces] = lwalloc(sizeof(TFACE));
|
|
|
|
tgeom->faces[tgeom->nfaces]->rings = NULL;
|
|
|
|
tgeom->faces[tgeom->nfaces]->nrings = 0;
|
|
|
|
tgeom->faces[tgeom->nfaces]->nedges = 0;
|
|
|
|
tgeom->faces[tgeom->nfaces]->maxedges = 0;
|
|
|
|
|
|
|
|
/* Compute edge on triangle */
|
|
|
|
for (i=1 ; i < triangle->points->npoints ; i++)
|
|
|
|
{
|
|
|
|
POINT4D p1, p2;
|
|
|
|
|
|
|
|
getPoint4d_p(triangle->points, i-1, &p1);
|
|
|
|
getPoint4d_p(triangle->points, i, &p2);
|
|
|
|
|
|
|
|
tgeom_add_face_edge(tgeom, tgeom->nfaces, &p1, &p2);
|
|
|
|
}
|
|
|
|
|
|
|
|
tgeom->nfaces++;
|
|
|
|
|
|
|
|
return tgeom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free a tgeom struct
|
|
|
|
* and even the geometries inside
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
tgeom_free(TGEOM *tgeom)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
|
|
|
|
/* bbox */
|
|
|
|
if (tgeom->bbox) lwfree(tgeom->bbox);
|
|
|
|
|
|
|
|
/* edges */
|
2010-08-30 09:06:40 +00:00
|
|
|
for (i=1 ; i <= tgeom->nedges ; i++)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
lwfree(tgeom->edges[i]->e);
|
|
|
|
lwfree(tgeom->edges[i]->s);
|
|
|
|
lwfree(tgeom->edges[i]);
|
|
|
|
}
|
|
|
|
if (tgeom->edges) lwfree(tgeom->edges);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* faces */
|
|
|
|
for (i=0 ; i < tgeom->nfaces ; i++)
|
|
|
|
{
|
|
|
|
/* edges array */
|
|
|
|
if (tgeom->faces[i]->edges)
|
|
|
|
lwfree(tgeom->faces[i]->edges);
|
|
|
|
|
|
|
|
/* rings */
|
|
|
|
for (j=0 ; j < tgeom->faces[i]->nrings ; j++)
|
|
|
|
ptarray_free(tgeom->faces[i]->rings[j]);
|
|
|
|
if (tgeom->faces[i]->rings)
|
|
|
|
lwfree(tgeom->faces[i]->rings);
|
|
|
|
|
|
|
|
lwfree(tgeom->faces[i]);
|
|
|
|
}
|
|
|
|
if (tgeom->faces) lwfree(tgeom->faces);
|
|
|
|
|
|
|
|
lwfree(tgeom);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return a TSERIALIZED pointer from an LWGEOM
|
|
|
|
*/
|
|
|
|
TSERIALIZED*
|
2010-08-30 09:06:40 +00:00
|
|
|
tserialized_from_lwgeom(LWGEOM *lwgeom)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
assert(lwgeom);
|
|
|
|
|
|
|
|
return tgeom_serialize(tgeom_from_lwgeom(lwgeom));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return a TGEOM pointer from an LWGEOM
|
2010-08-30 09:06:40 +00:00
|
|
|
* Caution: Geometries from LWGEOM are copied
|
2010-08-30 06:49:51 +00:00
|
|
|
*/
|
|
|
|
TGEOM*
|
2010-12-01 20:28:29 +00:00
|
|
|
tgeom_from_lwgeom(const LWGEOM *lwgeom)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
int i, solid;
|
|
|
|
LWTIN *tin;
|
|
|
|
LWPSURFACE *psurf;
|
|
|
|
TGEOM *tgeom = NULL;
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
tgeom = tgeom_new(0, FLAGS_GET_Z(lwgeom->flags), FLAGS_GET_M(lwgeom->flags));
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-12-13 19:25:15 +00:00
|
|
|
if (lwgeom->srid < 1) tgeom->srid = SRID_UNKNOWN;
|
|
|
|
else tgeom->srid = lwgeom->srid;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
if (lwgeom_is_empty(lwgeom)) return tgeom;
|
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
switch (lwgeom->type)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-08-30 09:06:40 +00:00
|
|
|
case TINTYPE:
|
|
|
|
tgeom->type = TINTYPE;
|
|
|
|
tin = (LWTIN *) lwgeom;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
for (i=0 ; i < tin->ngeoms ; i++)
|
|
|
|
tgeom = tgeom_add_triangle(tgeom,
|
|
|
|
(LWTRIANGLE *) tin->geoms[i]);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case POLYHEDRALSURFACETYPE:
|
|
|
|
tgeom->type = POLYHEDRALSURFACETYPE;
|
|
|
|
psurf = (LWPSURFACE *) lwgeom;
|
|
|
|
for (i=0 ; i < psurf->ngeoms ; i++)
|
|
|
|
tgeom = tgeom_add_polygon(tgeom,
|
|
|
|
(LWPOLY *) psurf->geoms[i]);
|
|
|
|
|
|
|
|
break;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* TODO handle COLLECTIONTYPE */
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
default:
|
|
|
|
lwerror("tgeom_from_lwgeom: unknown geometry type %i - %s",
|
2010-11-21 19:02:23 +00:00
|
|
|
tgeom->type, lwtype_name(tgeom->type));
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (solid=1, i=1 ; i <= tgeom->nedges ; i++)
|
|
|
|
{
|
|
|
|
if (tgeom->edges[i]->count != 2)
|
|
|
|
{
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "no solid, edges: [%i], count: [%i] (%lf,%lf,%lf,%lf)->(%lf,%lf,%lf,%lf)\n",
|
2010-08-30 09:06:40 +00:00
|
|
|
i, tgeom->edges[i]->count,
|
|
|
|
tgeom->edges[i]->s->x, tgeom->edges[i]->s->y,
|
2010-08-31 19:14:43 +00:00
|
|
|
tgeom->edges[i]->s->z, tgeom->edges[i]->s->m,
|
2010-08-30 09:06:40 +00:00
|
|
|
tgeom->edges[i]->e->x, tgeom->edges[i]->e->y,
|
|
|
|
tgeom->edges[i]->e->z, tgeom->edges[i]->e->m);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
solid = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FLAGS_SET_SOLID(tgeom->flags, solid);
|
|
|
|
|
|
|
|
return tgeom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return a LWGEOM pointer from an TSERIALIZED struct
|
|
|
|
*/
|
|
|
|
LWGEOM*
|
|
|
|
lwgeom_from_tserialized(TSERIALIZED *t)
|
|
|
|
{
|
|
|
|
assert(t);
|
|
|
|
|
|
|
|
return lwgeom_from_tgeom(tgeom_deserialize(t));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return a LWGEOM pointer from an TGEOM struct
|
|
|
|
* Geometries are NOT copied
|
|
|
|
*/
|
|
|
|
LWGEOM*
|
|
|
|
lwgeom_from_tgeom(TGEOM *tgeom)
|
|
|
|
{
|
|
|
|
int i, j, k;
|
|
|
|
LWGEOM *geom;
|
2010-11-01 01:16:35 +00:00
|
|
|
POINTARRAY *dpa;
|
2010-08-30 06:49:51 +00:00
|
|
|
POINTARRAY **ppa;
|
2010-11-21 19:02:23 +00:00
|
|
|
int hasz, hasm, edge_id;
|
2010-08-30 06:49:51 +00:00
|
|
|
int dims=0;
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
assert(tgeom);
|
|
|
|
|
|
|
|
hasz=FLAGS_GET_Z(tgeom->flags);
|
|
|
|
hasm=FLAGS_GET_M(tgeom->flags);
|
|
|
|
|
2010-10-23 23:48:37 +00:00
|
|
|
geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, tgeom->srid, hasz, hasm);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
switch (tgeom->type)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-08-30 09:06:40 +00:00
|
|
|
case TINTYPE:
|
2010-11-21 19:02:23 +00:00
|
|
|
geom->type = TINTYPE;
|
2010-08-30 09:06:40 +00:00
|
|
|
for (i=0 ; i < tgeom->nfaces ; i++)
|
|
|
|
{
|
2010-11-21 19:02:23 +00:00
|
|
|
FLAGS_SET_Z(dims, hasz?1:0);
|
|
|
|
FLAGS_SET_M(dims, hasm?1:0);
|
2010-11-01 01:28:12 +00:00
|
|
|
dpa = ptarray_construct_empty(hasz, hasm, 4);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
|
|
|
for (j=0 ; j < tgeom->faces[i]->nedges ; j++)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-08-30 09:06:40 +00:00
|
|
|
edge_id = tgeom->faces[i]->edges[j];
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "TIN edge_id: %i\n", edge_id);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
|
|
|
assert(edge_id);
|
2010-08-30 06:49:51 +00:00
|
|
|
if (edge_id > 0)
|
2010-11-23 00:44:24 +00:00
|
|
|
ptarray_append_point(dpa, tgeom->edges[edge_id]->s, REPEATED_POINTS_OK);
|
2010-08-30 06:49:51 +00:00
|
|
|
else
|
2010-11-23 00:44:24 +00:00
|
|
|
ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, REPEATED_POINTS_OK);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
edge_id = tgeom->faces[i]->edges[0];
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "TIN edge_id: %i\n", edge_id);
|
2010-08-30 09:06:40 +00:00
|
|
|
if (edge_id > 0)
|
2010-11-23 00:44:24 +00:00
|
|
|
ptarray_append_point(dpa, tgeom->edges[edge_id]->s, REPEATED_POINTS_OK);
|
2010-08-30 09:06:40 +00:00
|
|
|
else
|
2010-11-23 00:44:24 +00:00
|
|
|
ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, REPEATED_POINTS_OK);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
|
|
|
geom = (LWGEOM *) lwtin_add_lwtriangle((LWTIN *) geom,
|
2010-11-01 01:16:35 +00:00
|
|
|
lwtriangle_construct(tgeom->srid, NULL, dpa));
|
2010-08-30 09:06:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case POLYHEDRALSURFACETYPE:
|
2010-11-21 19:02:23 +00:00
|
|
|
geom->type = POLYHEDRALSURFACETYPE;
|
2010-08-30 09:06:40 +00:00
|
|
|
for (i=0 ; i < tgeom->nfaces ; i++)
|
|
|
|
{
|
2010-11-21 19:02:23 +00:00
|
|
|
FLAGS_SET_Z(dims, hasz?1:0);
|
|
|
|
FLAGS_SET_M(dims, hasm?1:0);;
|
2010-11-01 01:28:12 +00:00
|
|
|
dpa = ptarray_construct_empty(hasz, hasm, 4);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
|
|
|
for (j=0 ; j < tgeom->faces[i]->nedges ; j++)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-08-30 09:06:40 +00:00
|
|
|
edge_id = tgeom->faces[i]->edges[j];
|
|
|
|
assert(edge_id);
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "POLYHEDRALSURFACE edge_id: %i\n", edge_id);
|
2010-08-30 06:49:51 +00:00
|
|
|
if (edge_id > 0)
|
2010-11-23 00:44:24 +00:00
|
|
|
ptarray_append_point(dpa, tgeom->edges[edge_id]->s, REPEATED_POINTS_OK);
|
2010-08-30 06:49:51 +00:00
|
|
|
else
|
2010-11-23 00:44:24 +00:00
|
|
|
ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, REPEATED_POINTS_OK);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
edge_id = tgeom->faces[i]->edges[0];
|
2010-08-31 19:14:43 +00:00
|
|
|
LWDEBUGF(3, "POLYHEDRALSURFACE edge_id: %i\n", edge_id);
|
2010-08-30 09:06:40 +00:00
|
|
|
if (edge_id > 0)
|
2010-11-23 00:44:24 +00:00
|
|
|
ptarray_append_point(dpa, tgeom->edges[edge_id]->s, REPEATED_POINTS_OK);
|
2010-08-30 09:06:40 +00:00
|
|
|
else
|
2010-11-23 00:44:24 +00:00
|
|
|
ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, REPEATED_POINTS_OK);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
|
|
|
ppa = lwalloc(sizeof(POINTARRAY*)
|
|
|
|
* (tgeom->faces[i]->nrings + 1));
|
2010-11-01 01:16:35 +00:00
|
|
|
ppa[0] = dpa;
|
2010-08-30 09:06:40 +00:00
|
|
|
for (k=0; k < tgeom->faces[i]->nrings ; k++)
|
|
|
|
ppa[k+1] = tgeom->faces[i]->rings[k];
|
|
|
|
|
|
|
|
geom = (LWGEOM *) lwpsurface_add_lwpoly((LWPSURFACE *) geom,
|
|
|
|
lwpoly_construct(tgeom->srid, NULL, k + 1, ppa));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2010-11-21 19:02:23 +00:00
|
|
|
lwerror("lwgeom_from_tgeom: Unkwnown type %i - %s\n",
|
|
|
|
tgeom->type, lwtype_name(tgeom->type));
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
2010-12-13 19:25:15 +00:00
|
|
|
if (geom->srid == 0) geom->srid = SRID_UNKNOWN;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
return geom;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute the memory size needed to serialize
|
2010-08-30 09:06:40 +00:00
|
|
|
* a TGEOM struct
|
2010-08-30 06:49:51 +00:00
|
|
|
*/
|
2010-08-30 09:06:40 +00:00
|
|
|
static size_t
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom_serialize_size(const TGEOM *tgeom)
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
size_t size;
|
|
|
|
int dims = FLAGS_NDIMS(tgeom->flags);
|
|
|
|
|
|
|
|
size = sizeof(uchar); /* type */
|
|
|
|
size += sizeof(uchar); /* flags */
|
|
|
|
size += sizeof(uint32); /* srid */
|
|
|
|
if (tgeom->bbox) size += sizeof(BOX3D); /* bbox */
|
|
|
|
|
|
|
|
size += sizeof(int); /* nedges */
|
|
|
|
size += (sizeof(double) * dims * 2 + 4) * tgeom->nedges;/* edges */
|
|
|
|
|
|
|
|
size += sizeof(int); /* nfaces */
|
2010-08-30 09:06:40 +00:00
|
|
|
for (i=0 ; i < tgeom->nfaces ; i++)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
size += sizeof(int); /* nedges */
|
|
|
|
size += sizeof(int) * tgeom->faces[i]->nedges; /* edges */
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
size += sizeof(int); /* nrings */
|
|
|
|
for (j=0 ; j < tgeom->faces[i]->nrings ; j++)
|
|
|
|
{
|
|
|
|
size += sizeof(int); /* npoints */
|
|
|
|
size += sizeof(double) * dims /* rings */
|
2010-08-30 09:06:40 +00:00
|
|
|
* tgeom->faces[i]->rings[j]->npoints;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Serialize a TGEOM to a buf
|
2010-08-30 09:06:40 +00:00
|
|
|
* retsize return by reference the allocated buf size
|
2010-08-30 06:49:51 +00:00
|
|
|
*/
|
2010-08-30 09:06:40 +00:00
|
|
|
static size_t
|
2010-08-30 06:49:51 +00:00
|
|
|
tgeom_serialize_buf(const TGEOM *tgeom, uchar *buf, size_t *retsize)
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
size_t size=0;
|
|
|
|
uchar *loc=buf;
|
|
|
|
int dims = FLAGS_NDIMS(tgeom->flags);
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
assert(buf);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* Write in the type. */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->type, sizeof(uchar));
|
|
|
|
loc += 1;
|
2010-08-30 06:49:51 +00:00
|
|
|
size += 1;
|
|
|
|
|
|
|
|
/* Write in the flags. */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->flags, sizeof(uchar));
|
|
|
|
loc += 1;
|
2010-08-30 06:49:51 +00:00
|
|
|
size += 1;
|
|
|
|
|
|
|
|
/* Write in the srid. */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->srid, sizeof(uint32));
|
|
|
|
loc += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
size += 4;
|
|
|
|
|
|
|
|
/* Write in the bbox. */
|
2010-08-30 09:06:40 +00:00
|
|
|
if (tgeom->bbox)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, tgeom->bbox, sizeof(BOX3D));
|
|
|
|
loc += sizeof(BOX3D);
|
|
|
|
size += sizeof(BOX3D);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Write in the number of edges (0=> EMPTY) */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->nedges, sizeof(int));
|
|
|
|
loc += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
size +=4;
|
|
|
|
|
|
|
|
/* Edges */
|
|
|
|
for (i=1 ; i <= tgeom->nedges ; i++)
|
|
|
|
{
|
|
|
|
/* 3DM specific handle */
|
|
|
|
if (!FLAGS_GET_Z(tgeom->flags) && FLAGS_GET_M(tgeom->flags))
|
|
|
|
{
|
|
|
|
memcpy(loc, tgeom->edges[i]->s, 2 * sizeof(double));
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double) * 2;
|
2010-08-30 06:49:51 +00:00
|
|
|
memcpy(loc, &(tgeom->edges[i]->s->m), sizeof(double));
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double);
|
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
memcpy(loc, tgeom->edges[i]->e, 2 * sizeof(double));
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double) * 2;
|
2010-08-30 06:49:51 +00:00
|
|
|
memcpy(loc, &(tgeom->edges[i]->e->m), sizeof(double));
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
else /* 2D, 3DZ && 4D */
|
|
|
|
{
|
|
|
|
memcpy(loc, tgeom->edges[i]->s, dims * sizeof(double));
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double) * dims;
|
2010-08-30 06:49:51 +00:00
|
|
|
memcpy(loc, tgeom->edges[i]->e, dims * sizeof(double));
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double) * dims;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->edges[i]->count, sizeof(int));
|
|
|
|
loc += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
size += sizeof(double) * dims * 2 + 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* Write in the number of faces */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->nfaces, sizeof(int));
|
|
|
|
loc += 4;
|
|
|
|
size += 4;
|
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* Faces */
|
|
|
|
for (i=0 ; i < tgeom->nfaces ; i++)
|
|
|
|
{
|
|
|
|
/* Write in the number of edges */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->faces[i]->nedges, sizeof(int));
|
|
|
|
loc += 4;
|
|
|
|
size += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* Write in the edges array */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, tgeom->faces[i]->edges,
|
|
|
|
sizeof(int) * tgeom->faces[i]->nedges);
|
|
|
|
loc += 4 * tgeom->faces[i]->nedges;
|
|
|
|
size += 4 * tgeom->faces[i]->nedges;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* Write the number of rings */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->faces[i]->nrings, sizeof(int));
|
|
|
|
loc += 4;
|
|
|
|
size += 4;
|
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
for (j=0 ; j < tgeom->faces[i]->nrings ; j++)
|
|
|
|
{
|
|
|
|
/* Write the number of points */
|
2010-08-30 09:06:40 +00:00
|
|
|
memcpy(loc, &tgeom->faces[i]->rings[j]->npoints, sizeof(int));
|
|
|
|
loc += 4;
|
|
|
|
size += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* Write the points */
|
|
|
|
memcpy(loc, getPoint_internal(tgeom->faces[i]->rings[j], 0),
|
2010-08-30 09:06:40 +00:00
|
|
|
sizeof(double) * dims * tgeom->faces[i]->rings[j]->npoints);
|
2010-08-30 06:49:51 +00:00
|
|
|
loc += sizeof(double) * dims * tgeom->faces[i]->rings[j]->npoints;
|
|
|
|
size += sizeof(double) * dims * tgeom->faces[i]->rings[j]->npoints;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retsize) *retsize = size;
|
|
|
|
|
|
|
|
return (size_t) (loc - buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
/*
|
|
|
|
* Serialize a tgeom struct and return a
|
2010-08-30 06:49:51 +00:00
|
|
|
* TSERIALIZED pointer
|
|
|
|
*/
|
|
|
|
TSERIALIZED *
|
|
|
|
tgeom_serialize(const TGEOM *tgeom)
|
|
|
|
{
|
|
|
|
size_t size, retsize;
|
|
|
|
TSERIALIZED * t;
|
2010-08-30 09:06:40 +00:00
|
|
|
uchar *data;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
size = tgeom_serialize_size(tgeom);
|
|
|
|
data = lwalloc(size);
|
|
|
|
tgeom_serialize_buf(tgeom, data, &retsize);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
if ( retsize != size )
|
|
|
|
{
|
|
|
|
lwerror("tgeom_serialize_size returned %d, ..serialize_buf returned %d",
|
|
|
|
size, retsize);
|
|
|
|
}
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
t = lwalloc(sizeof(TSERIALIZED));
|
2010-08-30 09:06:40 +00:00
|
|
|
t->flags = tgeom->flags;
|
2010-08-30 06:49:51 +00:00
|
|
|
t->srid = tgeom->srid;
|
|
|
|
t->data = data;
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/*
|
2010-09-05 15:25:50 +00:00
|
|
|
* We are aping PgSQL code here, PostGIS code should use
|
|
|
|
* VARSIZE to set this for real.
|
|
|
|
*/
|
2010-08-30 09:06:40 +00:00
|
|
|
t->size = retsize << 2;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
return t;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2010-08-30 09:06:40 +00:00
|
|
|
* Deserialize a TSERIALIZED struct and
|
2010-08-30 06:49:51 +00:00
|
|
|
* return a TGEOM pointer
|
|
|
|
*/
|
|
|
|
TGEOM *
|
2010-08-30 09:06:40 +00:00
|
|
|
tgeom_deserialize(TSERIALIZED *serialized_form)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
uchar type, flags;
|
|
|
|
TGEOM *result;
|
|
|
|
uchar *loc, *data;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
assert(serialized_form);
|
|
|
|
assert(serialized_form->data);
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
data = serialized_form->data;
|
|
|
|
|
|
|
|
/* type and flags */
|
|
|
|
type = data[0];
|
|
|
|
flags = data[1];
|
|
|
|
result = tgeom_new(type, FLAGS_GET_Z(flags), FLAGS_GET_M(flags));
|
|
|
|
loc = data + 2;
|
|
|
|
|
|
|
|
/* srid */
|
|
|
|
result->srid = lw_get_int32(loc);
|
|
|
|
loc += 4;
|
|
|
|
|
|
|
|
/* bbox */
|
|
|
|
if (FLAGS_GET_BBOX(flags))
|
|
|
|
{
|
|
|
|
result->bbox = lwalloc(sizeof(BOX3D));
|
|
|
|
memcpy(result->bbox, loc, sizeof(BOX3D));
|
|
|
|
loc += sizeof(BOX3D);
|
2010-08-30 09:06:40 +00:00
|
|
|
}
|
|
|
|
else result->bbox = NULL;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* edges number (0=> EMPTY) */
|
2010-08-30 09:06:40 +00:00
|
|
|
result->nedges = lw_get_int32(loc);
|
|
|
|
loc += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* edges */
|
2010-08-31 19:14:43 +00:00
|
|
|
result->edges = lwalloc(sizeof(TEDGE*) * (result->nedges + 1));
|
2010-08-30 06:49:51 +00:00
|
|
|
for (i=1 ; i <= result->nedges ; i++)
|
|
|
|
{
|
|
|
|
result->edges[i] = lwalloc(sizeof(TEDGE));
|
|
|
|
result->edges[i]->s = lwalloc(sizeof(POINT4D));
|
|
|
|
result->edges[i]->e = lwalloc(sizeof(POINT4D));
|
|
|
|
|
|
|
|
/* 3DM specific handle */
|
|
|
|
if (!FLAGS_GET_Z(result->flags) && FLAGS_GET_M(result->flags))
|
|
|
|
{
|
|
|
|
memcpy(result->edges[i]->s, loc, sizeof(double) * 2);
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double) * 2;
|
2010-08-30 06:49:51 +00:00
|
|
|
memcpy(&(result->edges[i]->s->m), loc, sizeof(double));
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
memcpy(result->edges[i]->e, loc, sizeof(double) * 2);
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double) * 2;
|
2010-08-30 06:49:51 +00:00
|
|
|
memcpy(&(result->edges[i]->e->m), loc, sizeof(double));
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
else /* 2D,3DZ && 4D */
|
|
|
|
{
|
|
|
|
memcpy(result->edges[i]->s, loc,
|
2010-08-30 09:06:40 +00:00
|
|
|
sizeof(double) * FLAGS_NDIMS(flags));
|
|
|
|
loc += sizeof(double) * FLAGS_NDIMS(flags);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
result->edges[i]->e = lwalloc(sizeof(POINT4D));
|
|
|
|
memcpy(result->edges[i]->e, loc,
|
2010-08-30 09:06:40 +00:00
|
|
|
sizeof(double) * FLAGS_NDIMS(flags));
|
|
|
|
loc += sizeof(double) * FLAGS_NDIMS(flags);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
result->edges[i]->count = lw_get_int32(loc);
|
|
|
|
loc += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
2010-08-30 09:06:40 +00:00
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* faces number */
|
2010-08-30 09:06:40 +00:00
|
|
|
result->nfaces = lw_get_int32(loc);
|
|
|
|
loc += 4;
|
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/* faces */
|
2010-08-31 19:14:43 +00:00
|
|
|
result->faces = lwalloc(sizeof(TFACE*) * result->nfaces);
|
2010-08-30 06:49:51 +00:00
|
|
|
for (i=0 ; i < result->nfaces ; i++)
|
|
|
|
{
|
|
|
|
result->faces[i] = lwalloc(sizeof(TFACE));
|
|
|
|
|
|
|
|
/* number of edges */
|
2010-08-30 09:06:40 +00:00
|
|
|
result->faces[i]->nedges = lw_get_int32(loc);
|
|
|
|
loc += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* edges array */
|
2010-08-31 19:14:43 +00:00
|
|
|
result->faces[i]->edges = lwalloc(sizeof(TEDGE*)
|
2010-08-30 09:06:40 +00:00
|
|
|
* result->faces[i]->nedges);
|
2010-08-31 19:14:43 +00:00
|
|
|
memcpy(result->faces[i]->edges, loc, sizeof(TEDGE*)
|
2010-08-30 09:06:40 +00:00
|
|
|
* result->faces[i]->nedges);
|
|
|
|
loc += 4 * result->faces[i]->nedges;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* number of rings */
|
2010-08-30 09:06:40 +00:00
|
|
|
result->faces[i]->nrings = lw_get_int32(loc);
|
|
|
|
loc += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
if (result->faces[i]->nrings)
|
|
|
|
result->faces[i]->rings = lwalloc(sizeof(POINTARRAY*)
|
2010-08-30 09:06:40 +00:00
|
|
|
* result->faces[i]->nrings);
|
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
for (j=0 ; j < result->faces[i]->nrings ; j++)
|
|
|
|
{
|
|
|
|
int npoints;
|
|
|
|
|
|
|
|
/* number of points */
|
2010-08-30 09:06:40 +00:00
|
|
|
npoints = lw_get_int32(loc);
|
|
|
|
loc += 4;
|
2010-08-30 06:49:51 +00:00
|
|
|
|
|
|
|
/* pointarray */
|
2010-11-04 23:21:06 +00:00
|
|
|
result->faces[i]->rings[j] = ptarray_construct_reference_data(FLAGS_GET_Z(flags), FLAGS_GET_M(flags), npoints, loc);
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
loc += sizeof(double)* FLAGS_NDIMS(flags) * npoints;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
return result;
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-05 15:25:50 +00:00
|
|
|
/*
|
|
|
|
* Indicate if an given LWGEOM is or not a solid
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lwgeom_is_solid(LWGEOM *lwgeom)
|
|
|
|
{
|
|
|
|
int solid=0;
|
|
|
|
TGEOM *tgeom;
|
|
|
|
|
|
|
|
assert(lwgeom);
|
|
|
|
|
|
|
|
/* Obvious case who could'nt be solid */
|
2010-11-21 19:02:23 +00:00
|
|
|
if (lwgeom->type != POLYHEDRALSURFACETYPE && lwgeom->type != TINTYPE) return 0;
|
|
|
|
if (!FLAGS_GET_Z(lwgeom->flags)) return 0;
|
2010-09-05 15:25:50 +00:00
|
|
|
|
|
|
|
/* Use TGEOM convert to know */
|
|
|
|
tgeom = tgeom_from_lwgeom(lwgeom);
|
|
|
|
solid = FLAGS_GET_SOLID(tgeom->flags);
|
|
|
|
tgeom_free(tgeom);
|
|
|
|
|
|
|
|
return solid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-06 12:53:47 +00:00
|
|
|
/*
|
|
|
|
* Compute 2D perimeter of a TGEOM
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
tgeom_perimeter2d(TGEOM* tgeom)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
double hz, vt, bdy = 0.0;
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
|
|
|
|
if (tgeom->type != POLYHEDRALSURFACETYPE && tgeom->type != TINTYPE)
|
|
|
|
lwerror("tgeom_perimeter2d called with wrong type: %i - %s",
|
|
|
|
tgeom->type, lwtype_name(tgeom->type));
|
|
|
|
|
|
|
|
/* Solid have a 0.0 length perimeter */
|
|
|
|
if (FLAGS_GET_SOLID(tgeom->flags)) return bdy;
|
|
|
|
|
|
|
|
for (i=1 ; i <= tgeom->nedges ; i++)
|
|
|
|
{
|
|
|
|
if (tgeom->edges[i]->count == 1)
|
|
|
|
{
|
|
|
|
hz = tgeom->edges[i]->s->x - tgeom->edges[i]->e->x;
|
|
|
|
vt = tgeom->edges[i]->s->y - tgeom->edges[i]->e->y;
|
|
|
|
bdy += sqrt(hz*hz + vt*vt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bdy;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute 2D/3D perimeter of a TGEOM
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
tgeom_perimeter(TGEOM* tgeom)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
double hz, vt, ht, bdy = 0.0;
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
|
|
|
|
if (tgeom->type != POLYHEDRALSURFACETYPE && tgeom->type != TINTYPE)
|
|
|
|
lwerror("tgeom_perimeter called with wrong type: %i - %s",
|
|
|
|
tgeom->type, lwtype_name(tgeom->type));
|
|
|
|
|
|
|
|
/* Solid have a 0.0 length perimeter */
|
|
|
|
if (FLAGS_GET_SOLID(tgeom->flags)) return bdy;
|
|
|
|
|
|
|
|
/* If no Z use 2d function instead */
|
|
|
|
if (!FLAGS_GET_Z(tgeom->flags)) return tgeom_perimeter2d(tgeom);
|
|
|
|
|
|
|
|
for (i=1 ; i <= tgeom->nedges ; i++)
|
|
|
|
{
|
|
|
|
if (tgeom->edges[i]->count == 1)
|
|
|
|
{
|
|
|
|
hz = tgeom->edges[i]->s->x - tgeom->edges[i]->e->x;
|
|
|
|
vt = tgeom->edges[i]->s->y - tgeom->edges[i]->e->y;
|
|
|
|
ht = tgeom->edges[i]->s->z - tgeom->edges[i]->e->z;
|
|
|
|
bdy += sqrt(hz*hz + vt*vt + ht*ht);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bdy;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-30 06:49:51 +00:00
|
|
|
/*
|
|
|
|
* Print a TGEOM struct
|
|
|
|
* Debug purpose only
|
|
|
|
*/
|
2010-08-30 09:06:40 +00:00
|
|
|
void
|
2010-08-30 06:49:51 +00:00
|
|
|
printTGEOM(TGEOM *tgeom)
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
assert(tgeom);
|
|
|
|
|
|
|
|
printf("TGEOM:\n");
|
2010-08-30 09:06:40 +00:00
|
|
|
printf(" - type %i, %s\n", tgeom->type, lwtype_name(tgeom->type));
|
2010-11-25 17:34:21 +00:00
|
|
|
printf(" - srid %i\n", tgeom->srid);
|
2010-08-30 06:49:51 +00:00
|
|
|
printf(" - nedges %i\n", tgeom->nedges);
|
|
|
|
printf(" - nfaces %i\n", tgeom->nfaces);
|
|
|
|
printf(" => EDGES:\n");
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
for (i=1 ; i <= tgeom->nedges ; i++)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
if (FLAGS_NDIMS(tgeom->flags) == 2)
|
|
|
|
printf(" [%i] (%lf,%lf) -> (%lf,%lf)\n", i,
|
2010-08-30 09:06:40 +00:00
|
|
|
tgeom->edges[i]->s->x,
|
|
|
|
tgeom->edges[i]->s->y,
|
|
|
|
tgeom->edges[i]->e->x,
|
|
|
|
tgeom->edges[i]->e->y);
|
2010-08-30 06:49:51 +00:00
|
|
|
else if (FLAGS_NDIMS(tgeom->flags) == 3)
|
|
|
|
printf(" [%i] (%lf,%lf,%lf) -> (%lf,%lf,%lf)\n", i,
|
2010-08-30 09:06:40 +00:00
|
|
|
tgeom->edges[i]->s->x,
|
|
|
|
tgeom->edges[i]->s->y,
|
|
|
|
tgeom->edges[i]->s->z,
|
|
|
|
tgeom->edges[i]->e->x,
|
|
|
|
tgeom->edges[i]->e->y,
|
|
|
|
tgeom->edges[i]->e->z);
|
|
|
|
else
|
2010-08-30 06:49:51 +00:00
|
|
|
printf(" [%i] (%lf,%lf,%lf,%lf) -> (%lf,%lf,%lf,%lf)\n", i,
|
2010-08-30 09:06:40 +00:00
|
|
|
tgeom->edges[i]->s->x,
|
|
|
|
tgeom->edges[i]->s->y,
|
|
|
|
tgeom->edges[i]->s->z,
|
|
|
|
tgeom->edges[i]->s->m,
|
|
|
|
tgeom->edges[i]->e->x,
|
|
|
|
tgeom->edges[i]->e->y,
|
|
|
|
tgeom->edges[i]->e->z,
|
|
|
|
tgeom->edges[i]->e->m);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
for (i=0 ; i < tgeom->nfaces ; i++)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-08-30 09:06:40 +00:00
|
|
|
printf(" => FACE [%i] nedges:%i nrings:%i\n", i,
|
|
|
|
tgeom->faces[i]->nedges, tgeom->faces[i]->nrings);
|
2010-08-30 06:49:51 +00:00
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
for (j=0 ; j < tgeom->faces[i]->nedges ; j++)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
2010-08-30 09:06:40 +00:00
|
|
|
int edge = tgeom->faces[i]->edges[j];
|
2010-08-30 06:49:51 +00:00
|
|
|
printf(" -> EDGES [%i]{%i} ", j, edge);
|
|
|
|
|
|
|
|
if (FLAGS_NDIMS(tgeom->flags) == 2)
|
|
|
|
{
|
|
|
|
if (tgeom->faces[i]->edges[j] > 0)
|
2010-08-30 09:06:40 +00:00
|
|
|
printf("(%lf,%lf) -> (%lf,%lf)\n",
|
|
|
|
tgeom->edges[edge]->s->x,
|
|
|
|
tgeom->edges[edge]->s->y,
|
|
|
|
tgeom->edges[edge]->e->x,
|
|
|
|
tgeom->edges[edge]->e->y);
|
2010-08-30 06:49:51 +00:00
|
|
|
else
|
2010-08-30 09:06:40 +00:00
|
|
|
printf("(%lf,%lf) -> (%lf,%lf)\n",
|
|
|
|
tgeom->edges[-edge]->e->x,
|
|
|
|
tgeom->edges[-edge]->e->y,
|
|
|
|
tgeom->edges[-edge]->s->x,
|
|
|
|
tgeom->edges[-edge]->s->y);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
2010-08-30 09:06:40 +00:00
|
|
|
else if (FLAGS_NDIMS(tgeom->flags) == 3)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
if (tgeom->faces[i]->edges[j] > 0)
|
2010-08-30 09:06:40 +00:00
|
|
|
printf("(%lf,%lf,%lf -> %lf,%lf,%lf)\n",
|
|
|
|
tgeom->edges[edge]->s->x,
|
|
|
|
tgeom->edges[edge]->s->y,
|
|
|
|
tgeom->edges[edge]->s->z,
|
|
|
|
tgeom->edges[edge]->e->x,
|
|
|
|
tgeom->edges[edge]->e->y,
|
|
|
|
tgeom->edges[edge]->e->z);
|
2010-08-30 06:49:51 +00:00
|
|
|
else
|
2010-08-30 09:06:40 +00:00
|
|
|
printf("(%lf,%lf,%lf -> %lf,%lf,%lf)\n",
|
|
|
|
tgeom->edges[-edge]->e->x,
|
|
|
|
tgeom->edges[-edge]->e->y,
|
|
|
|
tgeom->edges[-edge]->e->z,
|
|
|
|
tgeom->edges[-edge]->s->x,
|
|
|
|
tgeom->edges[-edge]->s->y,
|
|
|
|
tgeom->edges[-edge]->s->z);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
2010-08-30 09:06:40 +00:00
|
|
|
else if (FLAGS_NDIMS(tgeom->flags) == 4)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
if (tgeom->faces[i]->edges[j] > 0)
|
2010-08-30 09:06:40 +00:00
|
|
|
printf("(%lf,%lf,%lf,%lf -> %lf,%lf,%lf,%lf)\n",
|
|
|
|
tgeom->edges[edge]->s->x,
|
|
|
|
tgeom->edges[edge]->s->y,
|
|
|
|
tgeom->edges[edge]->s->z,
|
|
|
|
tgeom->edges[edge]->s->m,
|
|
|
|
tgeom->edges[edge]->e->x,
|
|
|
|
tgeom->edges[edge]->e->y,
|
|
|
|
tgeom->edges[edge]->e->z,
|
|
|
|
tgeom->edges[edge]->e->m);
|
2010-08-30 06:49:51 +00:00
|
|
|
else
|
2010-08-30 09:06:40 +00:00
|
|
|
printf("(%lf,%lf,%lf,%lf -> %lf,%lf,%lf,%lf)\n",
|
|
|
|
tgeom->edges[-edge]->e->x,
|
|
|
|
tgeom->edges[-edge]->e->y,
|
|
|
|
tgeom->edges[-edge]->e->z,
|
|
|
|
tgeom->edges[-edge]->e->m,
|
|
|
|
tgeom->edges[-edge]->s->x,
|
|
|
|
tgeom->edges[-edge]->s->y,
|
|
|
|
tgeom->edges[-edge]->s->z,
|
|
|
|
tgeom->edges[-edge]->s->m);
|
2010-08-30 06:49:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-30 09:06:40 +00:00
|
|
|
for (j=0 ; j < tgeom->faces[i]->nrings ; j++)
|
2010-08-30 06:49:51 +00:00
|
|
|
{
|
|
|
|
printf(" - Ring[%i/%i]", j, tgeom->faces[i]->nrings);
|
|
|
|
printPA(tgeom->faces[i]->rings[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|