From: Sandro Santilli Date: Thu, 8 Oct 2015 09:07:33 +0000 (+0000) Subject: Fix universe face splitting performance regression (#3321) X-Git-Tag: 2.3.0beta1~438 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8381df27738fb98b5f955a466574484d80b0f6c1;p=postgis Fix universe face splitting performance regression (#3321) 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 --- diff --git a/liblwgeom/liblwgeom_topo.h b/liblwgeom/liblwgeom_topo.h index 84cc4044b..e361eda06 100644 --- a/liblwgeom/liblwgeom_topo.h +++ b/liblwgeom/liblwgeom_topo.h @@ -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 ); /** diff --git a/liblwgeom/lwgeom_topo.c b/liblwgeom/lwgeom_topo.c index 85314085b..0a7b813c7 100644 --- a/liblwgeom/lwgeom_topo.c +++ b/liblwgeom/lwgeom_topo.c @@ -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; diff --git a/topology/postgis_topology.c b/topology/postgis_topology.c index e46ac1f2c..d7375dfd0 100644 --- a/topology/postgis_topology.c +++ b/topology/postgis_topology.c @@ -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);