]> granicus.if.org Git - postgis/commitdiff
Fix universe face splitting performance regression (#3321)
authorSandro Santilli <strk@keybit.net>
Thu, 8 Oct 2015 09:07:33 +0000 (09:07 +0000)
committerSandro Santilli <strk@keybit.net>
Thu, 8 Oct 2015 09:07:33 +0000 (09:07 +0000)
NOTE: breaks the liblwgeom-topo ABI from 2.2.0RC1, should never
      affect postgis (unless a 2.2.0RC1 version of it dynamically
      links to a 2.2.0RC1+ liblwgeom version)

git-svn-id: http://svn.osgeo.org/postgis/trunk@14225 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/liblwgeom_topo.h
liblwgeom/lwgeom_topo.c
topology/postgis_topology.c

index 84cc4044bf6a008237954187327bf09f2258781c..e361eda069f92ef44c1f22be5898bc69bb08a3bf 100644 (file)
@@ -618,7 +618,9 @@ typedef struct LWT_BE_CALLBACKS_T {
   );
 
   /**
+   * \brief
    * Get edges that have any of the given faces on the left or right side
+   * and optionally whose bounding box overlaps the given one.
    *
    * @param topo the topology to act upon
    * @param ids an array of face identifiers
@@ -628,6 +630,8 @@ typedef struct LWT_BE_CALLBACKS_T {
    *                 section for semantic.
    * @param fields fields to be filled in the returned structure, see
    *               LWT_COL_EDGE_* macros
+   * @param box optional bounding box to further restrict matches, use
+   *            NULL for no further restriction.
    *
    * @return an array of edges identifiers or NULL in the following cases:
    *         - no edge found ("numelems" is set to 0)
@@ -635,7 +639,8 @@ typedef struct LWT_BE_CALLBACKS_T {
    */
   LWT_ISO_EDGE* (*getEdgeByFace) (
       const LWT_BE_TOPOLOGY* topo,
-      const LWT_ELEMID* ids, int* numelems, int fields
+      const LWT_ELEMID* ids, int* numelems, int fields,
+      const GBOX *box
   );
 
   /**
@@ -649,6 +654,8 @@ typedef struct LWT_BE_CALLBACKS_T {
    *                 otherwise see @return section for semantic.
    * @param fields fields to be filled in the returned structure, see
    *               LWT_COL_NODE_* macros
+   * @param box optional bounding box to further restrict matches, use
+   *            NULL for no further restriction.
    *
    * @return an array of nodes or NULL in the following cases:
    *         - no nod found ("numelems" is set to 0)
@@ -656,7 +663,8 @@ typedef struct LWT_BE_CALLBACKS_T {
    */
   LWT_ISO_NODE* (*getNodeByFace) (
       const LWT_BE_TOPOLOGY* topo,
-      const LWT_ELEMID* faces, int* numelems, int fields
+      const LWT_ELEMID* faces, int* numelems, int fields,
+      const GBOX *box
   );
 
   /**
index 85314085bb5c6d258bcdabb40dcfba9b1d460091..0a7b813c75b72583c408a2b5506cb2d805a31d8f 100644 (file)
@@ -248,16 +248,16 @@ lwt_be_getEdgeByNode(LWT_TOPOLOGY* topo, const LWT_ELEMID* ids,
 
 static LWT_ISO_EDGE*
 lwt_be_getEdgeByFace(LWT_TOPOLOGY* topo, const LWT_ELEMID* ids,
-                   int* numelems, int fields)
+                   int* numelems, int fields, const GBOX *box)
 {
-  CBT3(topo, getEdgeByFace, ids, numelems, fields);
+  CBT4(topo, getEdgeByFace, ids, numelems, fields, box);
 }
 
 static LWT_ISO_NODE*
 lwt_be_getNodeByFace(LWT_TOPOLOGY* topo, const LWT_ELEMID* ids,
-                   int* numelems, int fields)
+                   int* numelems, int fields, const GBOX *box)
 {
-  CBT3(topo, getNodeByFace, ids, numelems, fields);
+  CBT4(topo, getNodeByFace, ids, numelems, fields, box);
 }
 
 LWT_ISO_EDGE*
@@ -1985,7 +1985,7 @@ _lwt_AddFaceSplit( LWT_TOPOLOGY* topo,
                LWT_COL_EDGE_GEOM
                ;
   numfaceedges = 1;
-  edges = lwt_be_getEdgeByFace( topo, &face, &numfaceedges, fields );
+  edges = lwt_be_getEdgeByFace( topo, &face, &numfaceedges, fields, newface.mbr );
   if ( numfaceedges == -1 ) {
     lwfree( signed_edge_ids );
     _lwt_release_edges(ring_edges, numedges);
@@ -2206,7 +2206,7 @@ _lwt_AddFaceSplit( LWT_TOPOLOGY* topo,
   int numisonodes = 1;
   fields = LWT_COL_NODE_NODE_ID | LWT_COL_NODE_GEOM;
   LWT_ISO_NODE *nodes = lwt_be_getNodeByFace(topo, &face,
-                                             &numisonodes, fields);
+                                             &numisonodes, fields, newface.mbr);
   if ( numisonodes == -1 ) {
     lwfree( signed_edge_ids );
     lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
@@ -2800,7 +2800,7 @@ lwt_GetFaceGeometry(LWT_TOPOLOGY* topo, LWT_ELEMID faceid)
            LWT_COL_EDGE_FACE_LEFT |
            LWT_COL_EDGE_FACE_RIGHT
            ;
-  edges = lwt_be_getEdgeByFace( topo, &faceid, &numfaceedges, fields );
+  edges = lwt_be_getEdgeByFace( topo, &faceid, &numfaceedges, fields, NULL );
   if ( numfaceedges == -1 ) {
     lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
     return NULL;
@@ -3017,7 +3017,7 @@ lwt_GetFaceEdges(LWT_TOPOLOGY* topo, LWT_ELEMID face_id, LWT_ELEMID **out )
            LWT_COL_EDGE_FACE_LEFT |
            LWT_COL_EDGE_FACE_RIGHT
            ;
-  edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields );
+  edges = lwt_be_getEdgeByFace( topo, &face_id, &numfaceedges, fields, NULL );
   if ( numfaceedges == -1 ) {
     lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
     return -1;
index e46ac1f2c83fe7a251f578f1e5e363604a5c785d..d7375dfd088eac381143de272e04e790c924a7f5 100644 (file)
@@ -883,21 +883,22 @@ cb_getEdgeByNode(const LWT_BE_TOPOLOGY* topo,
 
 static LWT_ISO_EDGE*
 cb_getEdgeByFace(const LWT_BE_TOPOLOGY* topo,
-      const LWT_ELEMID* ids, int* numelems, int fields)
+      const LWT_ELEMID* ids, int* numelems, int fields,
+      const GBOX *box)
 {
   LWT_ISO_EDGE *edges;
        int spi_result;
   MemoryContext oldcontext = CurrentMemoryContext;
-
   StringInfoData sqldata;
   StringInfo sql = &sqldata;
   int i;
+  char *hexbox;
 
   initStringInfo(sql);
   appendStringInfoString(sql, "SELECT ");
   addEdgeFields(sql, fields, 0);
   appendStringInfo(sql, " FROM \"%s\".edge_data", topo->name);
-  appendStringInfoString(sql, " WHERE left_face IN (");
+  appendStringInfoString(sql, " WHERE left_face IN (");
   // add all identifiers here
   for (i=0; i<*numelems; ++i) {
     appendStringInfo(sql, "%s%" LWTFMT_ELEMID, (i?",":""), ids[i]);
@@ -907,7 +908,13 @@ cb_getEdgeByFace(const LWT_BE_TOPOLOGY* topo,
   for (i=0; i<*numelems; ++i) {
     appendStringInfo(sql, "%s%" LWTFMT_ELEMID, (i?",":""), ids[i]);
   }
-  appendStringInfoString(sql, ")");
+  appendStringInfoString(sql, ") )");
+  if ( box )
+  {
+    hexbox = _box2d_to_hexwkb(box, topo->srid);
+    appendStringInfo(sql, " AND geom && '%s'::geometry", hexbox);
+    lwfree(hexbox);
+  }
 
   POSTGIS_DEBUGF(1, "cb_getEdgeByFace query: %s", sql->data);
   POSTGIS_DEBUGF(1, "data_changed is %d", topo->be_data->data_changed);
@@ -1111,7 +1118,8 @@ cb_getNodeById(const LWT_BE_TOPOLOGY* topo,
 
 static LWT_ISO_NODE*
 cb_getNodeByFace(const LWT_BE_TOPOLOGY* topo,
-      const LWT_ELEMID* ids, int* numelems, int fields)
+      const LWT_ELEMID* ids, int* numelems, int fields,
+      const GBOX *box)
 {
   LWT_ISO_NODE *nodes;
        int spi_result;
@@ -1119,6 +1127,7 @@ cb_getNodeByFace(const LWT_BE_TOPOLOGY* topo,
   StringInfoData sqldata;
   StringInfo sql = &sqldata;
   int i;
+  char *hexbox;
 
   initStringInfo(sql);
   appendStringInfoString(sql, "SELECT ");
@@ -1130,6 +1139,12 @@ cb_getNodeByFace(const LWT_BE_TOPOLOGY* topo,
     appendStringInfo(sql, "%s%" LWTFMT_ELEMID, (i?",":""), ids[i]);
   }
   appendStringInfoString(sql, ")");
+  if ( box )
+  {
+    hexbox = _box2d_to_hexwkb(box, topo->srid);
+    appendStringInfo(sql, " AND geom && '%s'::geometry", hexbox);
+    lwfree(hexbox);
+  }
   POSTGIS_DEBUGF(1, "cb_getNodeByFace query: %s", sql->data);
   POSTGIS_DEBUGF(1, "data_changed is %d", topo->be_data->data_changed);
   spi_result = SPI_execute(sql->data, !topo->be_data->data_changed, 0);