PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ lwt_Polygonize()

int lwt_Polygonize ( LWT_TOPOLOGY topo)

Definition at line 7038 of file lwgeom_topo.c.

7039 {
7040  /*
7041  Fetch all edges
7042  Sort edges by edge_id
7043  Mark all edges' left and right face as -1
7044  Iteratively:
7045  Fetch next edge with left or right face == -1
7046  For each side with face == -1:
7047  Find ring on its side
7048  If ring is CCW:
7049  create a new face, assign to the ring edges' appropriate side
7050  If ring is CW (face needs to be same of external):
7051  assign a negative face_id the ring edges' appropriate side
7052  Now for each edge with a negative face_id on the side:
7053  Find containing face (mbr cache and all)
7054  Update with id of containing face
7055  */
7056 
7057  const LWT_BE_IFACE *iface = topo->be_iface;
7058  LWT_ISO_EDGE *edge;
7059  int numfaces = -1;
7060  LWT_ISO_EDGE_TABLE edgetable;
7061  LWT_EDGERING_ARRAY holes, shells;
7062  int i;
7063  int err = 0;
7064 
7065  LWT_EDGERING_ARRAY_INIT(&holes);
7066  LWT_EDGERING_ARRAY_INIT(&shells);
7067 
7068  initGEOS(lwnotice, lwgeom_geos_error);
7069 
7070  /*
7071  Check if Topology already contains some Face
7072  (ignoring the Universal Face)
7073  */
7074  numfaces = _lwt_CheckFacesExist(topo);
7075  if ( numfaces != 0 ) {
7076  if ( numfaces > 0 ) {
7077  /* Faces exist */
7078  lwerror("Polygonize: face table is not empty.");
7079  }
7080  /* Backend error, message should have been printed already */
7081  return -1;
7082  }
7083 
7084 
7085  edgetable.edges = _lwt_FetchAllEdges(topo, &(edgetable.size));
7086  if ( ! edgetable.edges ) {
7087  if (edgetable.size == 0) {
7088  /* not an error: no Edges */
7089  return 0;
7090  }
7091  /* error should have been printed already */
7092  return -1;
7093  }
7094 
7095  /* Sort edges by ID (to allow btree searches) */
7096  qsort(edgetable.edges, edgetable.size, sizeof(LWT_ISO_EDGE), compare_iso_edges_by_id);
7097 
7098  /* Mark all edges as unvisited */
7099  for (i=0; i<edgetable.size; ++i)
7100  edgetable.edges[i].face_left = edgetable.edges[i].face_right = -1;
7101 
7102  i = 0;
7103  while (1)
7104  {
7105  i = _lwt_FetchNextUnvisitedEdge(topo, &edgetable, i);
7106  if ( i < 0 ) break; /* end of unvisited */
7107  edge = &(edgetable.edges[i]);
7108 
7109  LWT_ELEMID newface = -1;
7110 
7111  LWDEBUGF(1, "Next face-missing edge has id:%d, face_left:%d, face_right:%d",
7112  edge->edge_id, edge->face_left, edge->face_right);
7113  if ( edge->face_left == -1 )
7114  {
7115  err = _lwt_RegisterFaceOnEdgeSide(topo, edge, 1, &edgetable,
7116  &holes, &shells, &newface);
7117  if ( err ) break;
7118  LWDEBUGF(1, "New face on the left of edge %d is %d",
7119  edge->edge_id, newface);
7120  edge->face_left = newface;
7121  }
7122  if ( edge->face_right == -1 )
7123  {
7124  err = _lwt_RegisterFaceOnEdgeSide(topo, edge, -1, &edgetable,
7125  &holes, &shells, &newface);
7126  if ( err ) break;
7127  LWDEBUGF(1, "New face on the right of edge %d is %d",
7128  edge->edge_id, newface);
7129  edge->face_right = newface;
7130  }
7131  }
7132 
7133  if ( err )
7134  {
7135  _lwt_release_edges(edgetable.edges, edgetable.size);
7136  LWT_EDGERING_ARRAY_CLEAN( &holes );
7137  LWT_EDGERING_ARRAY_CLEAN( &shells );
7138  lwerror("Errors fetching or registering face-missing edges: %s",
7139  lwt_be_lastErrorMessage(iface));
7140  return -1;
7141  }
7142 
7143  LWDEBUGF(1, "Found %d holes and %d shells", holes.size, shells.size);
7144 
7145  /* TODO: sort holes by pt.x, sort shells by bbox.xmin */
7146 
7147  /* Assign shells to holes */
7148  for (i=0; i<holes.size; ++i)
7149  {
7150  LWT_ELEMID containing_face;
7151  LWT_EDGERING *ring = holes.rings[i];
7152 
7153  containing_face = _lwt_FindFaceContainingRing(topo, ring, &shells);
7154  LWDEBUGF(1, "Ring %d contained by face %" LWTFMT_ELEMID, i, containing_face);
7155  if ( containing_face == -1 )
7156  {
7157  _lwt_release_edges(edgetable.edges, edgetable.size);
7158  LWT_EDGERING_ARRAY_CLEAN( &holes );
7159  LWT_EDGERING_ARRAY_CLEAN( &shells );
7160  lwerror("Errors finding face containing ring: %s",
7161  lwt_be_lastErrorMessage(iface));
7162  return -1;
7163  }
7164  int ret = _lwt_UpdateEdgeRingSideFace(topo, holes.rings[i], containing_face);
7165  if ( ret )
7166  {
7167  _lwt_release_edges(edgetable.edges, edgetable.size);
7168  LWT_EDGERING_ARRAY_CLEAN( &holes );
7169  LWT_EDGERING_ARRAY_CLEAN( &shells );
7170  lwerror("Errors updating edgering side face: %s",
7171  lwt_be_lastErrorMessage(iface));
7172  return -1;
7173  }
7174  }
7175 
7176  LWDEBUG(1, "All holes assigned, cleaning up");
7177 
7178  _lwt_release_edges(edgetable.edges, edgetable.size);
7179 
7180  /* delete all shell and hole EDGERINGS */
7181  LWT_EDGERING_ARRAY_CLEAN( &holes );
7182  LWT_EDGERING_ARRAY_CLEAN( &shells );
7183 
7184  return 0;
7185 }
void lwgeom_geos_error(const char *fmt,...)
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:119
static int _lwt_UpdateEdgeRingSideFace(LWT_TOPOLOGY *topo, LWT_EDGERING *ring, LWT_ELEMID face)
Definition: lwgeom_topo.c:6501
static int _lwt_CheckFacesExist(LWT_TOPOLOGY *topo)
Definition: lwgeom_topo.c:7018
#define LWT_EDGERING_ARRAY_INIT(a)
Definition: lwgeom_topo.c:6372
static int _lwt_RegisterFaceOnEdgeSide(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edge, int side, LWT_ISO_EDGE_TABLE *edges, LWT_EDGERING_ARRAY *holes, LWT_EDGERING_ARRAY *shells, LWT_ELEMID *registered)
Definition: lwgeom_topo.c:6805
static LWT_ELEMID _lwt_FindFaceContainingRing(LWT_TOPOLOGY *topo, LWT_EDGERING *ring, LWT_EDGERING_ARRAY *shells)
Definition: lwgeom_topo.c:6880
#define LWT_EDGERING_ARRAY_CLEAN(a)
Definition: lwgeom_topo.c:6381
static LWT_ISO_EDGE * _lwt_FetchAllEdges(LWT_TOPOLOGY *topo, int *numedges)
Definition: lwgeom_topo.c:6475
static int compare_iso_edges_by_id(const void *si1, const void *si2)
Definition: lwgeom_topo.c:6287
static int _lwt_FetchNextUnvisitedEdge(__attribute__((__unused__)) LWT_TOPOLOGY *topo, LWT_ISO_EDGE_TABLE *etab, int from)
Definition: lwgeom_topo.c:6464
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:43
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:465
LWT_EDGERING ** rings
Definition: lwgeom_topo.c:6366
LWT_ISO_EDGE * edges
Definition: lwgeom_topo.c:6282
LWT_ELEMID face_right
LWT_ELEMID face_left
LWT_ELEMID edge_id
const LWT_BE_IFACE * be_iface

References _lwt_CheckFacesExist(), _lwt_FetchAllEdges(), _lwt_FetchNextUnvisitedEdge(), _lwt_FindFaceContainingRing(), _lwt_RegisterFaceOnEdgeSide(), _lwt_release_edges(), _lwt_UpdateEdgeRingSideFace(), LWT_TOPOLOGY_T::be_iface, compare_iso_edges_by_id(), LWT_ISO_EDGE::edge_id, LWT_ISO_EDGE_TABLE_T::edges, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, LWDEBUG, LWDEBUGF, lwerror(), lwgeom_geos_error(), lwnotice(), lwt_be_lastErrorMessage(), LWT_EDGERING_ARRAY_CLEAN, LWT_EDGERING_ARRAY_INIT, LWTFMT_ELEMID, LWT_EDGERING_ARRAY_T::rings, LWT_ISO_EDGE_TABLE_T::size, and LWT_EDGERING_ARRAY_T::size.

Here is the call graph for this function: