From aacf8e6987d32249f2bfbf864cd29f668b91600e Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Mon, 29 Jun 2015 14:07:31 +0000 Subject: [PATCH] Implement ST_NewEdgesSplit in C Involved adding a new "deleteEdges" callback. Funded by Tuscany Region (Italy) - SITA (CIG: 60351023B8) git-svn-id: http://svn.osgeo.org/postgis/trunk@13738 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/liblwgeom_topo.h | 22 ++- liblwgeom/liblwgeom_topo_internal.h | 2 + liblwgeom/lwgeom_topo.c | 182 ++++++++++++++++++ topology/postgis_topology.c | 102 +++++++++- topology/sql/sqlmm.sql.in | 285 +--------------------------- 5 files changed, 304 insertions(+), 289 deletions(-) diff --git a/liblwgeom/liblwgeom_topo.h b/liblwgeom/liblwgeom_topo.h index f09225274..d2057c984 100644 --- a/liblwgeom/liblwgeom_topo.h +++ b/liblwgeom/liblwgeom_topo.h @@ -398,6 +398,22 @@ typedef struct LWT_BE_CALLBACKS_T { LWT_ELEMID split_edge, LWT_ELEMID new_edge1, LWT_ELEMID new_edge2 ); + /** + * Delete edges + * + * @param topo the topology to act upon + * @param sel_edge an LWT_ISO_EDGE object with selecting fields set. + * @param sel_fields fields used to select edges to be deleted, + * see LWT_COL_EDGE_* macros + * + * @return number of edges being deleted or -1 on error + * (@see lastErroMessage) + */ + int (*deleteEdges) ( + const LWT_BE_TOPOLOGY* topo, + const LWT_ISO_EDGE* sel_edge, int sel_fields + ); + } LWT_BE_CALLBACKS; @@ -815,7 +831,7 @@ void lwt_ChangeEdgeGeom(LWT_TOPOLOGY* topo, LWT_ELEMID edge, LWGEOM* geom); * @param edge identifier of the edge to be split * @param pt geometry of the new node * @param skipChecks if non-zero skips consistency checks - * (coincident node) + * (coincident node, point not on edge...) * @return the id of newly created node, or -1 on error * (liblwgeom error handler will be invoked with error message) * @@ -830,10 +846,12 @@ LWT_ELEMID lwt_ModEdgeSplit(LWT_TOPOLOGY* topo, LWT_ELEMID edge, LWPOINT* pt, in * @param topo the topology to operate on * @param edge identifier of the edge to be split * @param pt geometry of the new node + * @param skipChecks if non-zero skips consistency checks + * (coincident node, point not on edge...) * @return the id of newly created node * */ -LWT_ELEMID lwt_NewEdgesSplit(LWT_TOPOLOGY* topo, LWT_ELEMID edge, LWPOINT* pt); +LWT_ELEMID lwt_NewEdgesSplit(LWT_TOPOLOGY* topo, LWT_ELEMID edge, LWPOINT* pt, int skipChecks); /** * Merge two edges, modifying the first and deleting the second diff --git a/liblwgeom/liblwgeom_topo_internal.h b/liblwgeom/liblwgeom_topo_internal.h index aea576f98..c6fc38d5e 100644 --- a/liblwgeom/liblwgeom_topo_internal.h +++ b/liblwgeom/liblwgeom_topo_internal.h @@ -53,6 +53,8 @@ int lwt_be_insertEdges(LWT_TOPOLOGY* topo, LWT_ISO_EDGE* edge, int numelems); int lwt_be_updateEdges(LWT_TOPOLOGY* topo, const LWT_ISO_EDGE* sel_edge, int sel_fields, const LWT_ISO_EDGE* upd_edge, int upd_fields, const LWT_ISO_EDGE* exc_edge, int exc_fields); +int +lwt_be_deleteEdges(LWT_TOPOLOGY* topo, const LWT_ISO_EDGE* sel_edge, int sel_fields); LWT_ELEMID lwt_be_getFaceContainingPoint(LWT_TOPOLOGY* topo, LWPOINT* pt); diff --git a/liblwgeom/lwgeom_topo.c b/liblwgeom/lwgeom_topo.c index 963adfb5c..41f6a68cc 100644 --- a/liblwgeom/lwgeom_topo.c +++ b/liblwgeom/lwgeom_topo.c @@ -160,6 +160,14 @@ lwt_be_updateEdges(LWT_TOPOLOGY* topo, exc_edge, exc_fields); } +int +lwt_be_deleteEdges(LWT_TOPOLOGY* topo, + const LWT_ISO_EDGE* sel_edge, int sel_fields +) +{ + CBT2(topo, deleteEdges, sel_edge, sel_fields); +} + LWT_ELEMID lwt_be_getFaceContainingPoint(LWT_TOPOLOGY* topo, LWPOINT* pt) { @@ -496,3 +504,177 @@ lwt_ModEdgeSplit( LWT_TOPOLOGY* topo, LWT_ELEMID edge, /* return new node id */ return node.node_id; } + +LWT_ELEMID +lwt_NewEdgesSplit( LWT_TOPOLOGY* topo, LWT_ELEMID edge, + LWPOINT* pt, int skipISOChecks ) +{ + LWT_ISO_NODE node; + LWT_ISO_EDGE* oldedge = NULL; + LWCOLLECTION *split_col; + const LWGEOM *oldedge_geom; + const LWGEOM *newedge_geom; + LWT_ISO_EDGE newedges[2]; + //LWT_ISO_EDGE newedge1, newedge2; + LWT_ISO_EDGE seledge, updedge; + int ret; + + split_col = _lwt_EdgeSplit( topo, edge, pt, skipISOChecks, &oldedge ); + if ( ! split_col ) return -1; /* should have raised an exception */ + oldedge_geom = split_col->geoms[0]; + newedge_geom = split_col->geoms[1]; + + /* Add new node, getting new id back */ + node.node_id = -1; + node.containing_face = -1; /* means not-isolated */ + node.geom = pt; + if ( ! lwt_be_insertNodes(topo, &node, 1) ) + { + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + if (node.node_id == -1) { + /* should have been set by backend */ + lwerror("Backend coding error: " + "insertNodes callback did not return node_id"); + return -1; + } + + /* Delete the old edge */ + seledge.edge_id = edge; + ret = lwt_be_deleteEdges(topo, &seledge, LWT_COL_EDGE_EDGE_ID); + if ( ret == -1 ) { + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + + /* Get new edges identifiers */ + newedges[0].edge_id = lwt_be_getNextEdgeId(topo); + if ( newedges[0].edge_id == -1 ) { + lwcollection_release(split_col); + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + newedges[1].edge_id = lwt_be_getNextEdgeId(topo); + if ( newedges[1].edge_id == -1 ) { + lwcollection_release(split_col); + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + + /* Define the first new edge (to new node) */ + newedges[0].start_node = oldedge->start_node; + newedges[0].end_node = node.node_id; + newedges[0].face_left = oldedge->face_left; + newedges[0].face_right = oldedge->face_right; + newedges[0].next_left = newedges[1].edge_id; + if ( oldedge->next_right == edge ) + newedges[0].next_right = newedges[0].edge_id; + else if ( oldedge->next_right == -edge ) + newedges[0].next_right = -newedges[1].edge_id; + else + newedges[0].next_right = oldedge->next_right; + newedges[0].geom = lwgeom_as_lwline(oldedge_geom); + /* lwgeom_split of a line should only return lines ... */ + if ( ! newedges[0].geom ) { + lwcollection_release(split_col); + lwerror("first geometry in lwgeom_split output is not a line"); + return -1; + } + + /* Define the second new edge (from new node) */ + newedges[1].start_node = node.node_id; + newedges[1].end_node = oldedge->end_node; + newedges[1].face_left = oldedge->face_left; + newedges[1].face_right = oldedge->face_right; + newedges[1].next_right = -newedges[0].edge_id; + if ( oldedge->next_left == -edge ) + newedges[1].next_left = -newedges[1].edge_id; + else if ( oldedge->next_left == edge ) + newedges[1].next_left = newedges[0].edge_id; + else + newedges[1].next_left = oldedge->next_left; + newedges[1].geom = lwgeom_as_lwline(newedge_geom); + /* lwgeom_split of a line should only return lines ... */ + if ( ! newedges[1].geom ) { + lwcollection_release(split_col); + lwerror("second geometry in lwgeom_split output is not a line"); + return -1; + } + + /* Insert both new edges */ + ret = lwt_be_insertEdges(topo, newedges, 2); + if ( ret == -1 ) { + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } else if ( ret == 0 ) { + lwcollection_release(split_col); + lwerror("Insertion of split edge failed (no reason)"); + return -1; + } + + /* Update all next edge references pointing to old edge id */ + + updedge.next_right = newedges[1].edge_id; + seledge.next_right = edge; + seledge.start_node = oldedge->start_node; + ret = lwt_be_updateEdges(topo, + &seledge, LWT_COL_EDGE_NEXT_RIGHT|LWT_COL_EDGE_START_NODE, + &updedge, LWT_COL_EDGE_NEXT_RIGHT, + NULL, 0); + if ( ret == -1 ) { + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + + updedge.next_right = -newedges[0].edge_id; + seledge.next_right = -edge; + seledge.start_node = oldedge->end_node; + ret = lwt_be_updateEdges(topo, + &seledge, LWT_COL_EDGE_NEXT_RIGHT|LWT_COL_EDGE_START_NODE, + &updedge, LWT_COL_EDGE_NEXT_RIGHT, + NULL, 0); + if ( ret == -1 ) { + lwcollection_release(split_col); + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + + updedge.next_left = newedges[0].edge_id; + seledge.next_left = edge; + seledge.end_node = oldedge->start_node; + ret = lwt_be_updateEdges(topo, + &seledge, LWT_COL_EDGE_NEXT_LEFT|LWT_COL_EDGE_END_NODE, + &updedge, LWT_COL_EDGE_NEXT_LEFT, + NULL, 0); + if ( ret == -1 ) { + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + + updedge.next_left = -newedges[1].edge_id; + seledge.next_left = -edge; + seledge.end_node = oldedge->end_node; + ret = lwt_be_updateEdges(topo, + &seledge, LWT_COL_EDGE_NEXT_LEFT|LWT_COL_EDGE_END_NODE, + &updedge, LWT_COL_EDGE_NEXT_LEFT, + NULL, 0); + if ( ret == -1 ) { + lwcollection_release(split_col); + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + + /* Update TopoGeometries composition -- TODO */ + ret = lwt_be_updateTopoGeomEdgeSplit(topo, oldedge->edge_id, newedges[0].edge_id, newedges[1].edge_id); + if ( ! ret ) { + lwcollection_release(split_col); + lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface)); + return -1; + } + + lwcollection_release(split_col); + + /* return new node id */ + return node.node_id; +} diff --git a/topology/postgis_topology.c b/topology/postgis_topology.c index 70476ca07..40cdf9738 100644 --- a/topology/postgis_topology.c +++ b/topology/postgis_topology.c @@ -767,6 +767,34 @@ cb_updateEdges( const LWT_BE_TOPOLOGY* topo, return SPI_processed; } +static int +cb_deleteEdges( const LWT_BE_TOPOLOGY* topo, + const LWT_ISO_EDGE* sel_edge, int sel_fields ) +{ + int spi_result; + StringInfoData sqldata; + StringInfo sql = &sqldata; + + initStringInfo(sql); + appendStringInfo(sql, "DELETE FROM \"%s\".edge_data WHERE ", topo->name); + addEdgeUpdate( sql, sel_edge, sel_fields, 0, updSel ); + + /* lwpgnotice("cb_deleteEdges: %s", sql->data); */ + + spi_result = SPI_execute( sql->data, false, 0 ); + if ( spi_result != SPI_OK_DELETE ) + { + cberror(topo->be_data, "unexpected return (%d) from query execution: %s", + spi_result, sql->data); + return -1; + } + pfree(sqldata.data); + + lwpgnotice("cb_deleteEdges: delete query processed %d rows", SPI_processed); + + return SPI_processed; +} + static LWT_ELEMID cb_getNextEdgeId( const LWT_BE_TOPOLOGY* topo ) { @@ -819,15 +847,15 @@ cb_updateTopoGeomEdgeSplit ( const LWT_BE_TOPOLOGY* topo, } else { appendStringInfoString(sql, "DELETE"); } - appendStringInfo(sql, " FROM \"%s\".relation r, topology.layer l WHERE " + appendStringInfo( sql, " FROM \"%s\".relation r %s topology.layer l WHERE " "l.topology_id = %d AND l.level = 0 AND l.layer_id = r.layer_id " "AND abs(r.element_id) = %lld AND r.element_type = 2", - topo->name, topo->id, split_edge); + topo->name, (new_edge2 == -1 ? "," : "USING" ), topo->id, split_edge ); if ( new_edge2 != -1 ) { appendStringInfo(sql, " RETURNING %s", proj); } - spi_result = SPI_execute(sql->data, true, 0); + spi_result = SPI_execute(sql->data, new_edge2 == -1, 0); if ( spi_result != ( new_edge2 == -1 ? SPI_OK_SELECT : SPI_OK_DELETE_RETURNING ) ) { cberror(topo->be_data, "unexpected return (%d) from query execution: %s", spi_result, sql->data); @@ -964,7 +992,8 @@ LWT_BE_CALLBACKS be_callbacks = { cb_updateEdges, NULL, /* getFacesById */ cb_getFaceContainingPoint, - cb_updateTopoGeomEdgeSplit + cb_updateTopoGeomEdgeSplit, + cb_deleteEdges }; @@ -1074,6 +1103,71 @@ Datum ST_ModEdgeSplit(PG_FUNCTION_ARGS) PG_RETURN_INT32(node_id); } +/* ST_NewEdgesSplit(atopology, anedge, apoint) */ +Datum ST_NewEdgesSplit(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(ST_NewEdgesSplit); +Datum ST_NewEdgesSplit(PG_FUNCTION_ARGS) +{ + text* toponame_text; + char* toponame; + LWT_ELEMID edge_id; + LWT_ELEMID node_id; + GSERIALIZED *geom; + LWGEOM *lwgeom; + LWPOINT *pt; + LWT_TOPOLOGY *topo; + + if ( PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) ) { + lwpgerror("SQL/MM Spatial exception - null argument"); + PG_RETURN_NULL(); + } + + toponame_text = PG_GETARG_TEXT_P(0); + toponame = text2cstring(toponame_text); + PG_FREE_IF_COPY(toponame_text, 0); + + edge_id = PG_GETARG_INT32(1) ; + + geom = PG_GETARG_GSERIALIZED_P(2); + lwgeom = lwgeom_from_gserialized(geom); + pt = lwgeom_as_lwpoint(lwgeom); + if ( ! pt ) { + lwgeom_free(lwgeom); + PG_FREE_IF_COPY(geom, 2); + lwpgerror("ST_NewEdgesSplit third argument must be a point geometry"); + PG_RETURN_NULL(); + } + + if ( SPI_OK_CONNECT != SPI_connect() ) { + lwpgerror("Could not connect to SPI"); + PG_RETURN_NULL(); + } + + topo = lwt_LoadTopology(be_iface, toponame); + pfree(toponame); + if ( ! topo ) { + /* should never reach this point, as lwerror would raise an exception */ + SPI_finish(); + PG_RETURN_NULL(); + } + + POSTGIS_DEBUG(1, "Calling lwt_NewEdgesSplit"); + node_id = lwt_NewEdgesSplit(topo, edge_id, pt, 0); + POSTGIS_DEBUG(1, "lwt_NewEdgesSplit returned"); + lwgeom_free(lwgeom); + PG_FREE_IF_COPY(geom, 3); + lwt_FreeTopology(topo); + + if ( node_id == -1 ) { + /* should never reach this point, as lwerror would raise an exception */ + SPI_finish(); + PG_RETURN_NULL(); + } + + SPI_finish(); + PG_RETURN_INT32(node_id); +} + /* ST_AddIsoNode(atopology, aface, apoint) */ Datum ST_AddIsoNode(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(ST_AddIsoNode); diff --git a/topology/sql/sqlmm.sql.in b/topology/sql/sqlmm.sql.in index 564085ed7..3bc9232cf 100644 --- a/topology/sql/sqlmm.sql.in +++ b/topology/sql/sqlmm.sql.in @@ -1698,289 +1698,8 @@ LANGUAGE 'plpgsql' VOLATILE; -- CREATE OR REPLACE FUNCTION topology.ST_NewEdgesSplit(atopology varchar, anedge integer, apoint geometry) RETURNS INTEGER AS -$$ -DECLARE - oldedge RECORD; - rec RECORD; - tmp integer; - topoid integer; - nodeid integer; - nodepos float8; - edgeid1 integer; - edgeid2 integer; - edge1 geometry; - edge2 geometry; - ok BOOL; -BEGIN - - -- - -- All args required - -- - IF atopology IS NULL OR anedge IS NULL OR apoint IS NULL THEN - RAISE EXCEPTION - 'SQL/MM Spatial exception - null argument'; - END IF; - - -- Get topology id - BEGIN - SELECT id FROM topology.topology - INTO STRICT topoid WHERE name = atopology; - EXCEPTION - WHEN NO_DATA_FOUND THEN - RAISE EXCEPTION 'SQL/MM Spatial exception - invalid topology name'; - END; - - -- - -- Check edge existance - -- - ok = false; - FOR oldedge IN EXECUTE 'SELECT * FROM ' - || quote_ident(atopology) || '.edge_data ' || - ' WHERE edge_id = ' || anedge - LOOP - ok = true; - END LOOP; - IF NOT ok THEN - RAISE EXCEPTION - 'SQL/MM Spatial exception - non-existent edge'; - END IF; - - -- - -- Check that given point is Within(anedge.geom) - -- - IF NOT ST_Within(apoint, oldedge.geom) THEN - RAISE EXCEPTION - 'SQL/MM Spatial exception - point not on edge'; - END IF; - - -- - -- Check if a coincident node already exists - -- - FOR rec IN EXECUTE 'SELECT node_id FROM ' - || quote_ident(atopology) || '.node WHERE geom && $1 ' - || ' AND ST_X(geom) = ST_X($1) AND ST_Y(geom) = ST_Y($1)' - USING apoint - LOOP - RAISE EXCEPTION - 'SQL/MM Spatial exception - coincident node'; - END LOOP; - - -- - -- Get new node id - -- - FOR rec IN EXECUTE 'SELECT nextval(''' || - atopology || '.node_node_id_seq'')' - LOOP - nodeid = rec.nextval; - END LOOP; - - --RAISE NOTICE 'Next node id = % ', nodeid; - - -- - -- Add the new node - -- - EXECUTE 'INSERT INTO ' || quote_ident(atopology) - || '.node(node_id, geom) VALUES($1, $2)' - USING nodeid, apoint; - - -- - -- Delete the old edge - -- - EXECUTE 'DELETE FROM ' || quote_ident(atopology) - || '.edge_data WHERE edge_id = $1' - USING anedge; - - -- - -- Compute new edges - -- - edge2 := ST_Split(oldedge.geom, apoint); - edge1 := ST_GeometryN(edge2, 1); - edge2 := ST_GeometryN(edge2, 2); - - -- - -- Get ids for the new edges - -- - FOR rec IN EXECUTE 'SELECT nextval(''' || - atopology || '.edge_data_edge_id_seq'')' - LOOP - edgeid1 = rec.nextval; - END LOOP; - FOR rec IN EXECUTE 'SELECT nextval(''' || - atopology || '.edge_data_edge_id_seq'')' - LOOP - edgeid2 = rec.nextval; - END LOOP; - -#ifdef POSTGIS_TOPOLOGY_DEBUG - RAISE DEBUG ' inserting new edges % and % split from %', edgeid1, edgeid2, anedge; -#endif - - --RAISE NOTICE 'EdgeId1 % EdgeId2 %', edgeid1, edgeid2; - - --RAISE DEBUG 'oldedge.next_left_edge: %', oldedge.next_left_edge; - --RAISE DEBUG 'oldedge.next_right_edge: %', oldedge.next_right_edge; - - -- - -- Insert the two new edges - -- - EXECUTE 'INSERT INTO ' || quote_ident(atopology) - || '.edge VALUES(' - || edgeid1 -- edge_id - || ',' || oldedge.start_node -- start_node - || ',' || nodeid -- end_node - || ',' || edgeid2 -- next_left_edge - || ',' || CASE -- next_right_edge - WHEN - oldedge.next_right_edge = anedge - THEN edgeid1 - WHEN - oldedge.next_right_edge = -anedge - THEN -edgeid2 - ELSE oldedge.next_right_edge - END - || ',' || oldedge.left_face -- left_face - || ',' || oldedge.right_face -- right_face - || ',$1)' -- geom - USING edge1; - - EXECUTE 'INSERT INTO ' || quote_ident(atopology) - || '.edge VALUES(' - || edgeid2 -- edge_id - || ',' || nodeid -- start_node - || ',' || oldedge.end_node -- end_node - || ',' || CASE -- next_left_edge - WHEN - oldedge.next_left_edge = - -anedge - THEN -edgeid2 - WHEN - oldedge.next_left_edge = - anedge - THEN edgeid1 - ELSE oldedge.next_left_edge - END - || ',' || -edgeid1 -- next_right_edge - || ',' || oldedge.left_face -- left_face - || ',' || oldedge.right_face -- right_face - || ',$1)' -- geom - USING edge2; - - -- - -- Update all next edge references to match new layout (ST_NewEdgeSplit) - -- - - EXECUTE 'UPDATE ' || quote_ident(atopology) - || '.edge_data SET next_right_edge = ' - || edgeid2 - || ',' - || ' abs_next_right_edge = ' || edgeid2 - || ' WHERE next_right_edge = ' || anedge - || ' AND start_node = ' || oldedge.start_node - || ' AND edge_id NOT IN (' || edgeid1 || ',' || edgeid2 || ')' - ; - EXECUTE 'UPDATE ' || quote_ident(atopology) - || '.edge_data SET next_right_edge = ' - || -edgeid1 - || ',' - || ' abs_next_right_edge = ' || edgeid1 - || ' WHERE next_right_edge = ' || -anedge - || ' AND start_node = ' || oldedge.end_node - || ' AND edge_id NOT IN (' || edgeid1 || ',' || edgeid2 || ')' - ; - - EXECUTE 'UPDATE ' || quote_ident(atopology) - || '.edge_data SET next_left_edge = ' - || edgeid1 - || ',' - || ' abs_next_left_edge = ' || edgeid1 - || ' WHERE next_left_edge = ' || anedge - || ' AND end_node = ' || oldedge.start_node - || ' AND edge_id NOT IN (' || edgeid1 || ',' || edgeid2 || ')' - ; - EXECUTE 'UPDATE ' || quote_ident(atopology) - || '.edge_data SET ' - || ' next_left_edge = ' || -edgeid2 - || ',' - || ' abs_next_left_edge = ' || edgeid2 - || ' WHERE next_left_edge = ' || -anedge - || ' AND end_node = ' || oldedge.end_node - || ' AND edge_id NOT IN (' || edgeid1 || ',' || edgeid2 || ')' - ; - - -- - -- Update references in the Relation table. - -- We only take into considerations non-hierarchical - -- TopoGeometry here, for obvious reasons. - -- - FOR rec IN EXECUTE 'SELECT r.* FROM ' - || quote_ident(atopology) - || '.relation r, topology.layer l ' - || ' WHERE ' - || ' l.topology_id = ' || topoid - || ' AND l.level = 0 ' - || ' AND l.layer_id = r.layer_id ' - || ' AND abs(r.element_id) = ' || anedge - || ' AND r.element_type = 2' - LOOP - --RAISE NOTICE 'TopoGeometry % in layer % contains the edge being split', rec.topogeo_id, rec.layer_id; - - -- Delete old reference - EXECUTE 'DELETE FROM ' || quote_ident(atopology) - || '.relation ' - || ' WHERE ' - || 'layer_id = ' || rec.layer_id - || ' AND ' - || 'topogeo_id = ' || rec.topogeo_id - || ' AND ' - || 'element_type = ' || rec.element_type - || ' AND ' - || 'abs(element_id) = ' || anedge; - - -- Add new reference to edge1 - IF rec.element_id < 0 THEN - tmp = -edgeid1; - ELSE - tmp = edgeid1; - END IF; - EXECUTE 'INSERT INTO ' || quote_ident(atopology) - || '.relation ' - || ' VALUES( ' - || rec.topogeo_id - || ',' - || rec.layer_id - || ',' - || tmp - || ',' - || rec.element_type - || ')'; - - -- Add new reference to edge2 - IF rec.element_id < 0 THEN - tmp = -edgeid2; - ELSE - tmp = edgeid2; - END IF; - EXECUTE 'INSERT INTO ' || quote_ident(atopology) - || '.relation ' - || ' VALUES( ' - || rec.topogeo_id - || ',' - || rec.layer_id - || ',' - || tmp - || ',' - || rec.element_type - || ')'; - - END LOOP; - - --RAISE NOTICE 'Edge % split in edges % and % by node %', - -- anedge, edgeid1, edgeid2, nodeid; - - RETURN nodeid; -END -$$ -LANGUAGE 'plpgsql' VOLATILE; + 'MODULE_PATHNAME','ST_NewEdgesSplit' + LANGUAGE 'c' VOLATILE; --} ST_NewEdgesSplit --{ -- 2.40.0