PostGIS  2.2.7dev-r@@SVN_REVISION@@
lwpsurface.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * Copyright (C) 2001-2006 Refractions Research Inc.
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU General Public Licence. See the COPYING file.
10  *
11  **********************************************************************/
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include "liblwgeom_internal.h"
17 #include "lwgeom_log.h"
18 
19 
21 {
22  return (LWPSURFACE*)lwcollection_add_lwgeom((LWCOLLECTION*)mobj, (LWGEOM*)obj);
23 }
24 
25 
27 {
28  int i;
29  if ( ! psurf ) return;
30  if ( psurf->bbox )
31  lwfree(psurf->bbox);
32 
33  for ( i = 0; i < psurf->ngeoms; i++ )
34  if ( psurf->geoms && psurf->geoms[i] )
35  lwpoly_free(psurf->geoms[i]);
36 
37  if ( psurf->geoms )
38  lwfree(psurf->geoms);
39 
40  lwfree(psurf);
41 }
42 
43 
45 {
46  int i, j;
47  LWPOLY *patch;
48 
49  if (psurf->type != POLYHEDRALSURFACETYPE)
50  lwerror("printLWPSURFACE called with something else than a POLYHEDRALSURFACE");
51 
52  lwnotice("LWPSURFACE {");
53  lwnotice(" ndims = %i", (int)FLAGS_NDIMS(psurf->flags));
54  lwnotice(" SRID = %i", (int)psurf->srid);
55  lwnotice(" ngeoms = %i", (int)psurf->ngeoms);
56 
57  for (i=0; i<psurf->ngeoms; i++)
58  {
59  patch = (LWPOLY *) psurf->geoms[i];
60  for (j=0; j<patch->nrings; j++)
61  {
62  lwnotice(" RING # %i :",j);
63  printPA(patch->rings[j]);
64  }
65  }
66  lwnotice("}");
67 }
68 
69 
70 
71 
72 /*
73  * TODO rewrite all this stuff to be based on a truly topological model
74  */
75 
77 {
78  double ax, ay, az;
79  double bx, by, bz;
80  int cnt, face;
81 };
83 
84 /* We supposed that the geometry is valid
85  we could have wrong result if not */
86 int lwpsurface_is_closed(const LWPSURFACE *psurface)
87 {
88  int i, j, k;
89  int narcs, carc;
90  int found;
91  psurface_arcs arcs;
92  POINT4D pa, pb;
93  LWPOLY *patch;
94 
95  /* If surface is not 3D, it's can't be closed */
96  if (!FLAGS_GET_Z(psurface->flags)) return 0;
97 
98  /* If surface is less than 4 faces hard to be closed too */
99  if (psurface->ngeoms < 4) return 0;
100 
101  /* Max theorical arcs number if no one is shared ... */
102  for (i=0, narcs=0 ; i < psurface->ngeoms ; i++)
103  {
104  patch = (LWPOLY *) psurface->geoms[i];
105  narcs += patch->rings[0]->npoints - 1;
106  }
107 
108  arcs = lwalloc(sizeof(struct struct_psurface_arcs) * narcs);
109  for (i=0, carc=0; i < psurface->ngeoms ; i++)
110  {
111 
112  patch = (LWPOLY *) psurface->geoms[i];
113  for (j=0; j < patch->rings[0]->npoints - 1; j++)
114  {
115 
116  getPoint4d_p(patch->rings[0], j, &pa);
117  getPoint4d_p(patch->rings[0], j+1, &pb);
118 
119  /* remove redundant points if any */
120  if (pa.x == pb.x && pa.y == pb.y && pa.z == pb.z) continue;
121 
122  /* Make sure to order the 'lower' point first */
123  if ( (pa.x > pb.x) ||
124  (pa.x == pb.x && pa.y > pb.y) ||
125  (pa.x == pb.x && pa.y == pb.y && pa.z > pb.z) )
126  {
127  pa = pb;
128  getPoint4d_p(patch->rings[0], j, &pb);
129  }
130 
131  for (found=0, k=0; k < carc ; k++)
132  {
133 
134  if ( ( arcs[k].ax == pa.x && arcs[k].ay == pa.y &&
135  arcs[k].az == pa.z && arcs[k].bx == pb.x &&
136  arcs[k].by == pb.y && arcs[k].bz == pb.z &&
137  arcs[k].face != i) )
138  {
139  arcs[k].cnt++;
140  found = 1;
141 
142  /* Look like an invalid PolyhedralSurface
143  anyway not a closed one */
144  if (arcs[k].cnt > 2)
145  {
146  lwfree(arcs);
147  return 0;
148  }
149  }
150  }
151 
152  if (!found)
153  {
154  arcs[carc].cnt=1;
155  arcs[carc].face=i;
156  arcs[carc].ax = pa.x;
157  arcs[carc].ay = pa.y;
158  arcs[carc].az = pa.z;
159  arcs[carc].bx = pb.x;
160  arcs[carc].by = pb.y;
161  arcs[carc].bz = pb.z;
162  carc++;
163 
164  /* Look like an invalid PolyhedralSurface
165  anyway not a closed one */
166  if (carc > narcs)
167  {
168  lwfree(arcs);
169  return 0;
170  }
171  }
172  }
173  }
174 
175  /* A polyhedron is closed if each edge
176  is shared by exactly 2 faces */
177  for (k=0; k < carc ; k++)
178  {
179  if (arcs[k].cnt != 2)
180  {
181  lwfree(arcs);
182  return 0;
183  }
184  }
185  lwfree(arcs);
186 
187  /* Invalid Polyhedral case */
188  if (carc < psurface->ngeoms) return 0;
189 
190  return 1;
191 }
double x
Definition: liblwgeom.h:336
uint8_t flags
Definition: liblwgeom.h:553
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:61
void printLWPSURFACE(LWPSURFACE *psurf)
Definition: lwpsurface.c:44
void lwfree(void *mem)
Definition: lwutil.c:214
int npoints
Definition: liblwgeom.h:355
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:82
LWPOLY ** geoms
Definition: liblwgeom.h:558
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:79
GBOX * bbox
Definition: liblwgeom.h:554
POINTARRAY ** rings
Definition: liblwgeom.h:441
int nrings
Definition: liblwgeom.h:439
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:124
double z
Definition: liblwgeom.h:336
uint8_t type
Definition: liblwgeom.h:552
void printPA(POINTARRAY *pa)
Definition: lwgeom_api.c:598
int lwpsurface_is_closed(const LWPSURFACE *psurface)
Definition: lwpsurface.c:86
struct struct_psurface_arcs * psurface_arcs
Definition: lwpsurface.c:82
void lwpsurface_free(LWPSURFACE *psurf)
Definition: lwpsurface.c:26
void * lwalloc(size_t size)
Definition: lwutil.c:199
double y
Definition: liblwgeom.h:336
int32_t srid
Definition: liblwgeom.h:555
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:136
int ngeoms
Definition: liblwgeom.h:556
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:174
LWPSURFACE * lwpsurface_add_lwpoly(LWPSURFACE *mobj, const LWPOLY *obj)
Definition: lwpsurface.c:20
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:231