PostGIS  2.2.8dev-r@@SVN_REVISION@@

◆ _lwt_AddFaceSplit()

static LWT_ELEMID _lwt_AddFaceSplit ( LWT_TOPOLOGY topo,
LWT_ELEMID  sedge,
LWT_ELEMID  face,
int  mbr_only 
)
static

Definition at line 1769 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().

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