PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ lwt_Polygonize()

int lwt_Polygonize ( LWT_TOPOLOGY topo)

Definition at line 6778 of file lwgeom_topo.c.

6779{
6780 /*
6781 Fetch all edges
6782 Sort edges by edge_id
6783 Mark all edges' left and right face as -1
6784 Iteratively:
6785 Fetch next edge with left or right face == -1
6786 For each side with face == -1:
6787 Find ring on its side
6788 If ring is CCW:
6789 create a new face, assign to the ring edges' appropriate side
6790 If ring is CW (face needs to be same of external):
6791 assign a negative face_id the ring edges' appropriate side
6792 Now for each edge with a negative face_id on the side:
6793 Find containing face (mbr cache and all)
6794 Update with id of containing face
6795 */
6796
6797 const LWT_BE_IFACE *iface = topo->be_iface;
6798 LWT_ISO_EDGE *edge;
6799 int numfaces = -1;
6800 LWT_ISO_EDGE_TABLE edgetable;
6801 LWT_EDGERING_ARRAY holes, shells;
6802 int i;
6803 int err = 0;
6804
6806 LWT_EDGERING_ARRAY_INIT(&shells);
6807
6808 initGEOS(lwnotice, lwgeom_geos_error);
6809
6810 /*
6811 Check if Topology already contains some Face
6812 (ignoring the Universal Face)
6813 */
6814 numfaces = _lwt_CheckFacesExist(topo);
6815 if ( numfaces != 0 ) {
6816 if ( numfaces > 0 ) {
6817 /* Faces exist */
6818 lwerror("Polygonize: face table is not empty.");
6819 }
6820 /* Backend error, message should have been printed already */
6821 return -1;
6822 }
6823
6824
6825 edgetable.edges = _lwt_FetchAllEdges(topo, &(edgetable.size));
6826 if ( ! edgetable.edges ) {
6827 if (edgetable.size == 0) {
6828 /* not an error: no Edges */
6829 return 0;
6830 }
6831 /* error should have been printed already */
6832 return -1;
6833 }
6834
6835 /* Sort edges by ID (to allow btree searches) */
6836 qsort(edgetable.edges, edgetable.size, sizeof(LWT_ISO_EDGE), compare_iso_edges_by_id);
6837
6838 /* Mark all edges as unvisited */
6839 for (i=0; i<edgetable.size; ++i)
6840 edgetable.edges[i].face_left = edgetable.edges[i].face_right = -1;
6841
6842 i = 0;
6843 while (1)
6844 {
6845 i = _lwt_FetchNextUnvisitedEdge(topo, &edgetable, i);
6846 if ( i < 0 ) break; /* end of unvisited */
6847 edge = &(edgetable.edges[i]);
6848
6849 LWT_ELEMID newface = -1;
6850
6851 LWDEBUGF(1, "Next face-missing edge has id:%d, face_left:%d, face_right:%d",
6852 edge->edge_id, edge->face_left, edge->face_right);
6853 if ( edge->face_left == -1 )
6854 {
6855 err = _lwt_RegisterFaceOnEdgeSide(topo, edge, 1, &edgetable,
6856 &holes, &shells, &newface);
6857 if ( err ) break;
6858 LWDEBUGF(1, "New face on the left of edge %d is %d",
6859 edge->edge_id, newface);
6860 edge->face_left = newface;
6861 }
6862 if ( edge->face_right == -1 )
6863 {
6864 err = _lwt_RegisterFaceOnEdgeSide(topo, edge, -1, &edgetable,
6865 &holes, &shells, &newface);
6866 if ( err ) break;
6867 LWDEBUGF(1, "New face on the right of edge %d is %d",
6868 edge->edge_id, newface);
6869 edge->face_right = newface;
6870 }
6871 }
6872
6873 if ( err )
6874 {
6875 _lwt_release_edges(edgetable.edges, edgetable.size);
6876 LWT_EDGERING_ARRAY_CLEAN( &holes );
6877 LWT_EDGERING_ARRAY_CLEAN( &shells );
6878 lwerror("Errors fetching or registering face-missing edges: %s",
6880 return -1;
6881 }
6882
6883 LWDEBUGF(1, "Found %d holes and %d shells", holes.size, shells.size);
6884
6885 /* TODO: sort holes by pt.x, sort shells by bbox.xmin */
6886
6887 /* Assign shells to holes */
6888 for (i=0; i<holes.size; ++i)
6889 {
6890 LWT_ELEMID containing_face;
6891 LWT_EDGERING *ring = holes.rings[i];
6892
6893 containing_face = _lwt_FindFaceContainingRing(topo, ring, &shells);
6894 LWDEBUGF(1, "Ring %d contained by face %" LWTFMT_ELEMID, i, containing_face);
6895 if ( containing_face == -1 )
6896 {
6897 _lwt_release_edges(edgetable.edges, edgetable.size);
6898 LWT_EDGERING_ARRAY_CLEAN( &holes );
6899 LWT_EDGERING_ARRAY_CLEAN( &shells );
6900 lwerror("Errors finding face containing ring: %s",
6902 return -1;
6903 }
6904 int ret = _lwt_UpdateEdgeRingSideFace(topo, holes.rings[i], containing_face);
6905 if ( ret )
6906 {
6907 _lwt_release_edges(edgetable.edges, edgetable.size);
6908 LWT_EDGERING_ARRAY_CLEAN( &holes );
6909 LWT_EDGERING_ARRAY_CLEAN( &shells );
6910 lwerror("Errors updating edgering side face: %s",
6912 return -1;
6913 }
6914 }
6915
6916 LWDEBUG(1, "All holes assigned, cleaning up");
6917
6918 _lwt_release_edges(edgetable.edges, edgetable.size);
6919
6920 /* delete all shell and hole EDGERINGS */
6921 LWT_EDGERING_ARRAY_CLEAN( &holes );
6922 LWT_EDGERING_ARRAY_CLEAN( &shells );
6923
6924 return 0;
6925}
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
static int _lwt_UpdateEdgeRingSideFace(LWT_TOPOLOGY *topo, LWT_EDGERING *ring, LWT_ELEMID face)
static int _lwt_CheckFacesExist(LWT_TOPOLOGY *topo)
#define LWT_EDGERING_ARRAY_INIT(a)
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)
static LWT_ISO_EDGE * _lwt_FetchAllEdges(LWT_TOPOLOGY *topo, int *numedges)
static LWT_ELEMID _lwt_FindFaceContainingRing(LWT_TOPOLOGY *topo, LWT_EDGERING *ring, LWT_EDGERING_ARRAY *shells)
#define LWT_EDGERING_ARRAY_CLEAN(a)
static int compare_iso_edges_by_id(const void *si1, const void *si2)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
static int _lwt_FetchNextUnvisitedEdge(__attribute__((__unused__)) LWT_TOPOLOGY *topo, LWT_ISO_EDGE_TABLE *etab, int from)
#define LWTFMT_ELEMID
Definition lwgeom_topo.c:43
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
LWT_EDGERING ** rings
LWT_ISO_EDGE * edges
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: