PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ lwpsurface_is_closed()

int lwpsurface_is_closed ( const LWPSURFACE psurface)

Definition at line 99 of file lwpsurface.c.

100 {
101  uint32_t i, j, k;
102  uint32_t 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 theoretical 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 }
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:140
void lwfree(void *mem)
Definition: lwutil.c:244
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:123
void * lwalloc(size_t size)
Definition: lwutil.c:229
POINTARRAY ** rings
Definition: liblwgeom.h:460
LWPOLY ** geoms
Definition: liblwgeom.h:577
uint32_t ngeoms
Definition: liblwgeom.h:575
uint8_t flags
Definition: liblwgeom.h:572
double x
Definition: liblwgeom.h:355
double z
Definition: liblwgeom.h:355
double y
Definition: liblwgeom.h:355
uint32_t npoints
Definition: liblwgeom.h:374
unsigned int uint32_t
Definition: uthash.h:78

References struct_psurface_arcs::ax, struct_psurface_arcs::ay, struct_psurface_arcs::az, struct_psurface_arcs::bx, struct_psurface_arcs::by, struct_psurface_arcs::bz, struct_psurface_arcs::cnt, struct_psurface_arcs::face, LWPSURFACE::flags, FLAGS_GET_Z, LWPSURFACE::geoms, getPoint4d_p(), lwalloc(), lwfree(), LWPSURFACE::ngeoms, POINTARRAY::npoints, LWPOLY::rings, POINT4D::x, POINT4D::y, and POINT4D::z.

Referenced by lwgeom_dimension(), and lwgeom_is_closed().

Here is the call graph for this function:
Here is the caller graph for this function: