PostGIS  2.3.7dev-r@@SVN_REVISION@@
static LWT_ELEMID _lwt_AddFaceSplit ( LWT_TOPOLOGY topo,
LWT_ELEMID  sedge,
LWT_ELEMID  face,
int  mbr_only 
)
static

Definition at line 1775 of file lwgeom_topo.c.

References _lwt_GetInteriorEdgePoint(), _lwt_release_edges(), _lwt_release_faces(), _lwt_release_nodes(), LWT_TOPOLOGY_T::be_iface, LWT_ISO_NODE::containing_face, contains(), LWT_ISO_EDGE::edge_id, LWT_ISO_FACE::face_id, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, LWT_ISO_NODE::geom, LWT_ISO_EDGE::geom, lwalloc(), LWDEBUG, LWDEBUGF, lwerror(), lwfree(), LWGEOM2GEOS(), lwgeom_geos_errmsg, lwgeom_get_bbox(), lwpoint_as_lwgeom(), lwpoint_free(), lwpoint_make2d(), lwpoly_as_lwgeom(), lwpoly_construct(), lwpoly_free(), lwt_be_getEdgeByFace(), lwt_be_getEdgeById(), lwt_be_getFaceById(), lwt_be_getNodeByFace(), lwt_be_getRingEdges(), lwt_be_insertFaces(), lwt_be_lastErrorMessage(), lwt_be_updateEdgesById(), lwt_be_updateFacesById(), lwt_be_updateNodesById(), LWT_COL_EDGE_EDGE_ID, LWT_COL_EDGE_FACE_LEFT, LWT_COL_EDGE_FACE_RIGHT, LWT_COL_EDGE_GEOM, LWT_COL_FACE_ALL, LWT_COL_NODE_CONTAINING_FACE, LWT_COL_NODE_GEOM, LWT_COL_NODE_NODE_ID, LWTFMT_ELEMID, LWT_ISO_FACE::mbr, LWT_ISO_NODE::node_id, LWLINE::points, ptarray_append_ptarray(), ptarray_clone_deep(), ptarray_free(), ptarray_isccw(), ptarray_reverse(), POINT2D::x, and POINT2D::y.

Referenced by _lwt_AddEdge().

1778 {
1779  int numedges, numfaceedges, i, j;
1780  int newface_outside;
1781  int num_signed_edge_ids;
1782  LWT_ELEMID *signed_edge_ids;
1783  LWT_ELEMID *edge_ids;
1784  LWT_ISO_EDGE *edges;
1785  LWT_ISO_EDGE *ring_edges;
1786  LWT_ISO_EDGE *forward_edges = NULL;
1787  int forward_edges_count = 0;
1788  LWT_ISO_EDGE *backward_edges = NULL;
1789  int backward_edges_count = 0;
1790 
1791  signed_edge_ids = lwt_be_getRingEdges(topo, sedge,
1792  &num_signed_edge_ids, 0);
1793  if ( ! signed_edge_ids ) {
1794  lwerror("Backend error (no ring edges for edge %" LWTFMT_ELEMID "): %s",
1795  sedge, lwt_be_lastErrorMessage(topo->be_iface));
1796  return -2;
1797  }
1798  LWDEBUGF(1, "getRingEdges returned %d edges", num_signed_edge_ids);
1799 
1800  /* You can't get to the other side of an edge forming a ring */
1801  for (i=0; i<num_signed_edge_ids; ++i) {
1802  if ( signed_edge_ids[i] == -sedge ) {
1803  /* No split here */
1804  LWDEBUG(1, "not a ring");
1805  lwfree( signed_edge_ids );
1806  return 0;
1807  }
1808  }
1809 
1810  LWDEBUGF(1, "Edge %" LWTFMT_ELEMID " split face %" LWTFMT_ELEMID " (mbr_only:%d)",
1811  sedge, face, mbr_only);
1812 
1813  /* Construct a polygon using edges of the ring */
1814  numedges = 0;
1815  edge_ids = lwalloc(sizeof(LWT_ELEMID)*num_signed_edge_ids);
1816  for (i=0; i<num_signed_edge_ids; ++i) {
1817  int absid = llabs(signed_edge_ids[i]);
1818  int found = 0;
1819  /* Do not add the same edge twice */
1820  for (j=0; j<numedges; ++j) {
1821  if ( edge_ids[j] == absid ) {
1822  found = 1;
1823  break;
1824  }
1825  }
1826  if ( ! found ) edge_ids[numedges++] = absid;
1827  }
1828  i = numedges;
1829  ring_edges = lwt_be_getEdgeById(topo, edge_ids, &i,
1831  lwfree( edge_ids );
1832  if ( i == -1 )
1833  {
1834  lwfree( signed_edge_ids );
1835  /* ring_edges should be NULL */
1836  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1837  return -2;
1838  }
1839  else if ( i != numedges )
1840  {
1841  lwfree( signed_edge_ids );
1842  _lwt_release_edges(ring_edges, numedges);
1843  lwerror("Unexpected error: %d edges found when expecting %d", i, numedges);
1844  return -2;
1845  }
1846 
1847  /* Should now build a polygon with those edges, in the order
1848  * given by GetRingEdges.
1849  */
1850  POINTARRAY *pa = NULL;
1851  for ( i=0; i<num_signed_edge_ids; ++i )
1852  {
1853  LWT_ELEMID eid = signed_edge_ids[i];
1854  LWDEBUGF(1, "Edge %d in ring of edge %" LWTFMT_ELEMID " is edge %" LWTFMT_ELEMID,
1855  i, sedge, eid);
1856  LWT_ISO_EDGE *edge = NULL;
1857  POINTARRAY *epa;
1858  for ( j=0; j<numedges; ++j )
1859  {
1860  if ( ring_edges[j].edge_id == llabs(eid) )
1861  {
1862  edge = &(ring_edges[j]);
1863  break;
1864  }
1865  }
1866  if ( edge == NULL )
1867  {
1868  lwfree( signed_edge_ids );
1869  _lwt_release_edges(ring_edges, numedges);
1870  lwerror("missing edge that was found in ring edges loop");
1871  return -2;
1872  }
1873 
1874  if ( pa == NULL )
1875  {
1876  pa = ptarray_clone_deep(edge->geom->points);
1877  if ( eid < 0 ) ptarray_reverse(pa);
1878  }
1879  else
1880  {
1881  if ( eid < 0 )
1882  {
1883  epa = ptarray_clone_deep(edge->geom->points);
1884  ptarray_reverse(epa);
1885  ptarray_append_ptarray(pa, epa, 0);
1886  ptarray_free(epa);
1887  }
1888  else
1889  {
1890  /* avoid a clone here */
1891  ptarray_append_ptarray(pa, edge->geom->points, 0);
1892  }
1893  }
1894  }
1895  POINTARRAY **points = lwalloc(sizeof(POINTARRAY*));
1896  points[0] = pa;
1897  /* NOTE: the ring may very well have collapsed components,
1898  * which would make it topologically invalid
1899  */
1900  LWPOLY* shell = lwpoly_construct(0, 0, 1, points);
1901 
1902  int isccw = ptarray_isccw(pa);
1903  LWDEBUGF(1, "Ring of edge %" LWTFMT_ELEMID " is %sclockwise",
1904  sedge, isccw ? "counter" : "");
1905  const GBOX* shellbox = lwgeom_get_bbox(lwpoly_as_lwgeom(shell));
1906 
1907  if ( face == 0 )
1908  {
1909  /* Edge split the universe face */
1910  if ( ! isccw )
1911  {
1912  lwpoly_free(shell);
1913  lwfree( signed_edge_ids );
1914  _lwt_release_edges(ring_edges, numedges);
1915  /* Face on the left side of this ring is the universe face.
1916  * Next call (for the other side) should create the split face
1917  */
1918  LWDEBUG(1, "The left face of this clockwise ring is the universe, "
1919  "won't create a new face there");
1920  return -1;
1921  }
1922  }
1923 
1924  if ( mbr_only && face != 0 )
1925  {
1926  if ( isccw )
1927  {{
1928  LWT_ISO_FACE updface;
1929  updface.face_id = face;
1930  updface.mbr = (GBOX *)shellbox; /* const cast, we won't free it, later */
1931  int ret = lwt_be_updateFacesById( topo, &updface, 1 );
1932  if ( ret == -1 )
1933  {
1934  lwfree( signed_edge_ids );
1935  _lwt_release_edges(ring_edges, numedges);
1936  lwpoly_free(shell); /* NOTE: owns shellbox above */
1937  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1938  return -2;
1939  }
1940  if ( ret != 1 )
1941  {
1942  lwfree( signed_edge_ids );
1943  _lwt_release_edges(ring_edges, numedges);
1944  lwpoly_free(shell); /* NOTE: owns shellbox above */
1945  lwerror("Unexpected error: %d faces found when expecting 1", ret);
1946  return -2;
1947  }
1948  }}
1949  lwfree( signed_edge_ids );
1950  _lwt_release_edges(ring_edges, numedges);
1951  lwpoly_free(shell); /* NOTE: owns shellbox above */
1952  return -1; /* mbr only was requested */
1953  }
1954 
1955  LWT_ISO_FACE *oldface = NULL;
1956  LWT_ISO_FACE newface;
1957  newface.face_id = -1;
1958  if ( face != 0 && ! isccw)
1959  {{
1960  /* Face created an hole in an outer face */
1961  int nfaces = 1;
1962  oldface = lwt_be_getFaceById(topo, &face, &nfaces, LWT_COL_FACE_ALL);
1963  if ( nfaces == -1 )
1964  {
1965  lwfree( signed_edge_ids );
1966  lwpoly_free(shell); /* NOTE: owns shellbox */
1967  _lwt_release_edges(ring_edges, numedges);
1968  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1969  return -2;
1970  }
1971  if ( nfaces != 1 )
1972  {
1973  lwfree( signed_edge_ids );
1974  lwpoly_free(shell); /* NOTE: owns shellbox */
1975  _lwt_release_edges(ring_edges, numedges);
1976  lwerror("Unexpected error: %d faces found when expecting 1", nfaces);
1977  return -2;
1978  }
1979  newface.mbr = oldface->mbr;
1980  }}
1981  else
1982  {
1983  newface.mbr = (GBOX *)shellbox; /* const cast, we won't free it, later */
1984  }
1985 
1986  /* Insert the new face */
1987  int ret = lwt_be_insertFaces( topo, &newface, 1 );
1988  if ( ret == -1 )
1989  {
1990  lwfree( signed_edge_ids );
1991  lwpoly_free(shell); /* NOTE: owns shellbox */
1992  _lwt_release_edges(ring_edges, numedges);
1993  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1994  return -2;
1995  }
1996  if ( ret != 1 )
1997  {
1998  lwfree( signed_edge_ids );
1999  lwpoly_free(shell); /* NOTE: owns shellbox */
2000  _lwt_release_edges(ring_edges, numedges);
2001  lwerror("Unexpected error: %d faces inserted when expecting 1", ret);
2002  return -2;
2003  }
2004  if ( oldface ) {
2005  newface.mbr = NULL; /* it is a reference to oldface mbr... */
2006  _lwt_release_faces(oldface, 1);
2007  }
2008 
2009  /* Update side location of new face edges */
2010 
2011  /* We want the new face to be on the left, if possible */
2012  if ( face != 0 && ! isccw ) { /* ring is clockwise in a real face */
2013  /* face shrinked, must update all non-contained edges and nodes */
2014  LWDEBUG(1, "New face is on the outside of the ring, updating rings in former shell");
2015  newface_outside = 1;
2016  /* newface is outside */
2017  } else {
2018  LWDEBUG(1, "New face is on the inside of the ring, updating forward edges in new ring");
2019  newface_outside = 0;
2020  /* newface is inside */
2021  }
2022 
2023  /* Update edges bounding the old face */
2024  /* (1) fetch all edges where left_face or right_face is = oldface */
2025  int fields = LWT_COL_EDGE_EDGE_ID |
2029  ;
2030  numfaceedges = 1;
2031  edges = lwt_be_getEdgeByFace( topo, &face, &numfaceedges, fields, newface.mbr );
2032  if ( numfaceedges == -1 ) {
2033  lwfree( signed_edge_ids );
2034  _lwt_release_edges(ring_edges, numedges);
2035  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
2036  return -2;
2037  }
2038  LWDEBUGF(1, "lwt_be_getEdgeByFace returned %d edges", numfaceedges);
2039  GEOSGeometry *shellgg = 0;
2040  const GEOSPreparedGeometry* prepshell = 0;
2041  shellgg = LWGEOM2GEOS( lwpoly_as_lwgeom(shell), 0);
2042  if ( ! shellgg ) {
2043  lwpoly_free(shell);
2044  lwfree(signed_edge_ids);
2045  _lwt_release_edges(ring_edges, numedges);
2046  _lwt_release_edges(edges, numfaceedges);
2047  lwerror("Could not convert shell geometry to GEOS: %s", lwgeom_geos_errmsg);
2048  return -2;
2049  }
2050  prepshell = GEOSPrepare( shellgg );
2051  if ( ! prepshell ) {
2052  GEOSGeom_destroy(shellgg);
2053  lwpoly_free(shell);
2054  lwfree(signed_edge_ids);
2055  _lwt_release_edges(ring_edges, numedges);
2056  _lwt_release_edges(edges, numfaceedges);
2057  lwerror("Could not prepare shell geometry: %s", lwgeom_geos_errmsg);
2058  return -2;
2059  }
2060 
2061  if ( numfaceedges )
2062  {
2063  forward_edges = lwalloc(sizeof(LWT_ISO_EDGE)*numfaceedges);
2064  forward_edges_count = 0;
2065  backward_edges = lwalloc(sizeof(LWT_ISO_EDGE)*numfaceedges);
2066  backward_edges_count = 0;
2067 
2068  /* (2) loop over the results and: */
2069  for ( i=0; i<numfaceedges; ++i )
2070  {
2071  LWT_ISO_EDGE *e = &(edges[i]);
2072  int found = 0;
2073  int contains;
2074  GEOSGeometry *egg;
2075  LWPOINT *epgeom;
2076  POINT2D ep;
2077 
2078  /* (2.1) skip edges whose ID is in the list of boundary edges ? */
2079  for ( j=0; j<num_signed_edge_ids; ++j )
2080  {
2081  int seid = signed_edge_ids[j];
2082  if ( seid == e->edge_id )
2083  {
2084  /* IDEA: remove entry from signed_edge_ids ? */
2085  LWDEBUGF(1, "Edge %d is a forward edge of the new ring", e->edge_id);
2086  forward_edges[forward_edges_count].edge_id = e->edge_id;
2087  forward_edges[forward_edges_count++].face_left = newface.face_id;
2088  found++;
2089  if ( found == 2 ) break;
2090  }
2091  else if ( -seid == e->edge_id )
2092  {
2093  /* IDEA: remove entry from signed_edge_ids ? */
2094  LWDEBUGF(1, "Edge %d is a backward edge of the new ring", e->edge_id);
2095  backward_edges[backward_edges_count].edge_id = e->edge_id;
2096  backward_edges[backward_edges_count++].face_right = newface.face_id;
2097  found++;
2098  if ( found == 2 ) break;
2099  }
2100  }
2101  if ( found ) continue;
2102 
2103  /* We need to check only a single point
2104  * (to avoid collapsed elements of the shell polygon
2105  * giving false positive).
2106  * The point but must not be an endpoint.
2107  */
2108  if ( ! _lwt_GetInteriorEdgePoint(e->geom, &ep) )
2109  {
2110  GEOSPreparedGeom_destroy(prepshell);
2111  GEOSGeom_destroy(shellgg);
2112  lwfree(signed_edge_ids);
2113  lwpoly_free(shell);
2114  lwfree(forward_edges); /* contents owned by ring_edges */
2115  lwfree(backward_edges); /* contents owned by ring_edges */
2116  _lwt_release_edges(ring_edges, numedges);
2117  _lwt_release_edges(edges, numfaceedges);
2118  lwerror("Could not find interior point for edge %d: %s",
2120  return -2;
2121  }
2122 
2123  epgeom = lwpoint_make2d(0, ep.x, ep.y);
2124  egg = LWGEOM2GEOS( lwpoint_as_lwgeom(epgeom) , 0);
2125  lwpoint_free(epgeom);
2126  if ( ! egg ) {
2127  GEOSPreparedGeom_destroy(prepshell);
2128  GEOSGeom_destroy(shellgg);
2129  lwfree(signed_edge_ids);
2130  lwpoly_free(shell);
2131  lwfree(forward_edges); /* contents owned by ring_edges */
2132  lwfree(backward_edges); /* contents owned by ring_edges */
2133  _lwt_release_edges(ring_edges, numedges);
2134  _lwt_release_edges(edges, numfaceedges);
2135  lwerror("Could not convert edge geometry to GEOS: %s",
2137  return -2;
2138  }
2139  /* IDEA: can be optimized by computing this on our side rather
2140  * than on GEOS (saves conversion of big edges) */
2141  /* IDEA: check that bounding box shortcut is taken, or use
2142  * shellbox to do it here */
2143  contains = GEOSPreparedContains( prepshell, egg );
2144  GEOSGeom_destroy(egg);
2145  if ( contains == 2 )
2146  {
2147  GEOSPreparedGeom_destroy(prepshell);
2148  GEOSGeom_destroy(shellgg);
2149  lwfree(signed_edge_ids);
2150  lwpoly_free(shell);
2151  lwfree(forward_edges); /* contents owned by ring_edges */
2152  lwfree(backward_edges); /* contents owned by ring_edges */
2153  _lwt_release_edges(ring_edges, numedges);
2154  _lwt_release_edges(edges, numfaceedges);
2155  lwerror("GEOS exception on PreparedContains: %s", lwgeom_geos_errmsg);
2156  return -2;
2157  }
2158  LWDEBUGF(1, "Edge %d %scontained in new ring", e->edge_id,
2159  (contains?"":"not "));
2160 
2161  /* (2.2) skip edges (NOT, if newface_outside) contained in shell */
2162  if ( newface_outside )
2163  {
2164  if ( contains )
2165  {
2166  LWDEBUGF(1, "Edge %d contained in an hole of the new face",
2167  e->edge_id);
2168  continue;
2169  }
2170  }
2171  else
2172  {
2173  if ( ! contains )
2174  {
2175  LWDEBUGF(1, "Edge %d not contained in the face shell",
2176  e->edge_id);
2177  continue;
2178  }
2179  }
2180 
2181  /* (2.3) push to forward_edges if left_face = oface */
2182  if ( e->face_left == face )
2183  {
2184  LWDEBUGF(1, "Edge %d has new face on the left side", e->edge_id);
2185  forward_edges[forward_edges_count].edge_id = e->edge_id;
2186  forward_edges[forward_edges_count++].face_left = newface.face_id;
2187  }
2188 
2189  /* (2.4) push to backward_edges if right_face = oface */
2190  if ( e->face_right == face )
2191  {
2192  LWDEBUGF(1, "Edge %d has new face on the right side", e->edge_id);
2193  backward_edges[backward_edges_count].edge_id = e->edge_id;
2194  backward_edges[backward_edges_count++].face_right = newface.face_id;
2195  }
2196  }
2197 
2198  /* Update forward edges */
2199  if ( forward_edges_count )
2200  {
2201  ret = lwt_be_updateEdgesById(topo, forward_edges,
2202  forward_edges_count,
2204  if ( ret == -1 )
2205  {
2206  lwfree( signed_edge_ids );
2207  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
2208  return -2;
2209  }
2210  if ( ret != forward_edges_count )
2211  {
2212  lwfree( signed_edge_ids );
2213  lwerror("Unexpected error: %d edges updated when expecting %d",
2214  ret, forward_edges_count);
2215  return -2;
2216  }
2217  }
2218 
2219  /* Update backward edges */
2220  if ( backward_edges_count )
2221  {
2222  ret = lwt_be_updateEdgesById(topo, backward_edges,
2223  backward_edges_count,
2225  if ( ret == -1 )
2226  {
2227  lwfree( signed_edge_ids );
2228  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
2229  return -2;
2230  }
2231  if ( ret != backward_edges_count )
2232  {
2233  lwfree( signed_edge_ids );
2234  lwerror("Unexpected error: %d edges updated when expecting %d",
2235  ret, backward_edges_count);
2236  return -2;
2237  }
2238  }
2239 
2240  lwfree(forward_edges);
2241  lwfree(backward_edges);
2242 
2243  }
2244 
2245  _lwt_release_edges(ring_edges, numedges);
2246  _lwt_release_edges(edges, numfaceedges);
2247 
2248  /* Update isolated nodes which are now in new face */
2249  int numisonodes = 1;
2251  LWT_ISO_NODE *nodes = lwt_be_getNodeByFace(topo, &face,
2252  &numisonodes, fields, newface.mbr);
2253  if ( numisonodes == -1 ) {
2254  lwfree( signed_edge_ids );
2255  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
2256  return -2;
2257  }
2258  if ( numisonodes ) {
2259  LWT_ISO_NODE *updated_nodes = lwalloc(sizeof(LWT_ISO_NODE)*numisonodes);
2260  int nodes_to_update = 0;
2261  for (i=0; i<numisonodes; ++i)
2262  {
2263  LWT_ISO_NODE *n = &(nodes[i]);
2264  GEOSGeometry *ngg;
2265  ngg = LWGEOM2GEOS( lwpoint_as_lwgeom(n->geom), 0 );
2266  int contains;
2267  if ( ! ngg ) {
2268  _lwt_release_nodes(nodes, numisonodes);
2269  if ( prepshell ) GEOSPreparedGeom_destroy(prepshell);
2270  if ( shellgg ) GEOSGeom_destroy(shellgg);
2271  lwfree(signed_edge_ids);
2272  lwpoly_free(shell);
2273  lwerror("Could not convert node geometry to GEOS: %s",
2275  return -2;
2276  }
2277  contains = GEOSPreparedContains( prepshell, ngg );
2278  GEOSGeom_destroy(ngg);
2279  if ( contains == 2 )
2280  {
2281  _lwt_release_nodes(nodes, numisonodes);
2282  if ( prepshell ) GEOSPreparedGeom_destroy(prepshell);
2283  if ( shellgg ) GEOSGeom_destroy(shellgg);
2284  lwfree(signed_edge_ids);
2285  lwpoly_free(shell);
2286  lwerror("GEOS exception on PreparedContains: %s", lwgeom_geos_errmsg);
2287  return -2;
2288  }
2289  LWDEBUGF(1, "Node %d is %scontained in new ring, newface is %s",
2290  n->node_id, contains ? "" : "not ",
2291  newface_outside ? "outside" : "inside" );
2292  if ( newface_outside )
2293  {
2294  if ( contains )
2295  {
2296  LWDEBUGF(1, "Node %d contained in an hole of the new face",
2297  n->node_id);
2298  continue;
2299  }
2300  }
2301  else
2302  {
2303  if ( ! contains )
2304  {
2305  LWDEBUGF(1, "Node %d not contained in the face shell",
2306  n->node_id);
2307  continue;
2308  }
2309  }
2310  updated_nodes[nodes_to_update].node_id = n->node_id;
2311  updated_nodes[nodes_to_update++].containing_face =
2312  newface.face_id;
2313  LWDEBUGF(1, "Node %d will be updated", n->node_id);
2314  }
2315  _lwt_release_nodes(nodes, numisonodes);
2316  if ( nodes_to_update )
2317  {
2318  int ret = lwt_be_updateNodesById(topo, updated_nodes,
2319  nodes_to_update,
2321  if ( ret == -1 ) {
2322  lwfree( signed_edge_ids );
2323  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
2324  return -2;
2325  }
2326  }
2327  lwfree(updated_nodes);
2328  }
2329 
2330  GEOSPreparedGeom_destroy(prepshell);
2331  GEOSGeom_destroy(shellgg);
2332  lwfree(signed_edge_ids);
2333  lwpoly_free(shell);
2334 
2335  return newface.face_id;
2336 }
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:477
static int _lwt_GetInteriorEdgePoint(const LWLINE *edge, POINT2D *ip)
Definition: lwgeom_topo.c:1725
static LWT_ISO_FACE * lwt_be_getFaceById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:232
LWT_ELEMID face_left
#define LWT_COL_NODE_CONTAINING_FACE
static int lwt_be_insertFaces(LWT_TOPOLOGY *topo, LWT_ISO_FACE *face, int numelems)
Definition: lwgeom_topo.c:201
#define LWT_COL_EDGE_FACE_LEFT
LWT_ELEMID containing_face
static int lwt_be_updateEdgesById(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *edges, int numedges, int upd_fields)
Definition: lwgeom_topo.c:306
LWPOINT * geom
void lwfree(void *mem)
Definition: lwutil.c:242
#define LWT_COL_EDGE_FACE_RIGHT
LWPOINT * lwpoint_make2d(int srid, double x, double y)
Definition: lwpoint.c:145
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:195
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:330
Datum contains(PG_FUNCTION_ARGS)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
LWLINE * geom
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
LWT_ISO_EDGE * lwt_be_getEdgeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:225
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:252
double x
Definition: liblwgeom.h:327
static LWT_ISO_EDGE * lwt_be_getEdgeByFace(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields, const GBOX *box)
Definition: lwgeom_topo.c:246
int ptarray_isccw(const POINTARRAY *pa)
Definition: ptarray.c:1026
static int lwt_be_updateFacesById(LWT_TOPOLOGY *topo, const LWT_ISO_FACE *faces, int numfaces)
Definition: lwgeom_topo.c:298
LWPOLY * lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition: lwpoly.c:43
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:150
const LWT_BE_IFACE * be_iface
LWT_ELEMID face_id
static LWT_ISO_NODE * lwt_be_getNodeByFace(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields, const GBOX *box)
Definition: lwgeom_topo.c:253
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
Definition: lwgeom.c:653
int ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance)
Append a POINTARRAY, pa2 to the end of an existing POINTARRAY, pa1.
Definition: ptarray.c:187
LWT_ELEMID face_right
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
Definition: ptarray.c:634
LWT_ELEMID node_id
double y
Definition: liblwgeom.h:327
LWT_ELEMID edge_id
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, int autofix)
static LWT_ELEMID * lwt_be_getRingEdges(LWT_TOPOLOGY *topo, LWT_ELEMID edge, int *numedges, int limit)
Definition: lwgeom_topo.c:380
static int lwt_be_updateNodesById(LWT_TOPOLOGY *topo, const LWT_ISO_NODE *nodes, int numnodes, int upd_fields)
Definition: lwgeom_topo.c:314
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
#define LWT_COL_FACE_ALL
#define LWT_COL_NODE_NODE_ID
Node fields.
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:467
void ptarray_reverse(POINTARRAY *pa)
Definition: ptarray.c:343
#define LWT_COL_NODE_GEOM
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:267
LWT_INT64 LWT_ELEMID
Identifier of topology element.
static void _lwt_release_faces(LWT_ISO_FACE *faces, int num_faces)
Definition: lwgeom_topo.c:457
#define LWT_COL_EDGE_GEOM
void * lwalloc(size_t size)
Definition: lwutil.c:227
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:120
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:102
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:44
POINTARRAY * points
Definition: liblwgeom.h:421

Here is the call graph for this function:

Here is the caller graph for this function: