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