lwt_GetFaceEdges X
lwt_ChangeEdgeGeom X
lwt_RemoveIsoNode X
+lwt_RemoveIsoEdge X
lwt_MoveIsoNode X
lwt_RemEdgeModFace X
lwt_RemEdgeNewFace X
* For ST_RemoveIsoNode
*
* @param topo the topology to operate on
- * @param node the identifier of the nod to be moved
+ * @param node the identifier of the node to be moved
* @return 0 on success, -1 on error
* (liblwgeom error handler will be invoked with error message)
*
*/
int lwt_RemoveIsoNode(LWT_TOPOLOGY* topo, LWT_ELEMID node);
+/**
+ * Remove an isolated edge
+ *
+ * For ST_RemIsoEdge
+ *
+ * @param topo the topology to operate on
+ * @param edge the identifier of the edge to be moved
+ * @return 0 on success, -1 on error
+ * (liblwgeom error handler will be invoked with error message)
+ *
+ */
+int lwt_RemIsoEdge(LWT_TOPOLOGY* topo, LWT_ELEMID edge);
+
/**
* Add an isolated edge connecting two existing isolated nodes
*
n = lwt_be_deleteNodesById( topo, &nid, n );
if ( n == -1 )
{
- lwerror("SQL/MM Spatial exception - not isolated node");
+ lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
return -1;
}
if ( n != 1 )
return 0; /* success */
}
+int
+lwt_RemIsoEdge(LWT_TOPOLOGY* topo, LWT_ELEMID id)
+{
+ LWT_ISO_EDGE deledge;
+ LWT_ISO_EDGE *edge;
+ LWT_ELEMID nid[2];
+ int n = 1;
+ int i;
+
+ edge = lwt_be_getEdgeById( topo, &id, &n, LWT_COL_EDGE_START_NODE|
+ LWT_COL_EDGE_END_NODE |
+ LWT_COL_EDGE_FACE_LEFT |
+ LWT_COL_EDGE_FACE_RIGHT );
+ if ( ! edge )
+ {
+ lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
+ return -1;
+ }
+ if ( ! n )
+ {
+ lwerror("SQL/MM Spatial exception - non-existent edge");
+ return -1;
+ }
+ if ( n > 1 )
+ {
+ lwfree(edge);
+ lwerror("Corrupted topology: more than a single edge have id %"
+ LWTFMT_ELEMID, id);
+ return -1;
+ }
+
+ if ( edge[0].face_left != edge[0].face_right )
+ {
+ lwfree(edge);
+ lwerror("SQL/MM Spatial exception - not isolated edge");
+ return -1;
+ }
+
+ nid[0] = edge[0].start_node;
+ nid[1] = edge[0].end_node;
+ lwfree(edge);
+
+ n = 2;
+ edge = lwt_be_getEdgeByNode( topo, nid, &n, LWT_COL_EDGE_EDGE_ID );
+ if ( n == -1 )
+ {
+ lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
+ return -1;
+ }
+ for ( i=0; i<n; ++i )
+ {
+ if ( edge[i].edge_id == id ) continue;
+ lwfree(edge);
+ lwerror("SQL/MM Spatial exception - not isolated edge");
+ return -1;
+ }
+ if ( edge ) lwfree(edge);
+
+ deledge.edge_id = id;
+ n = lwt_be_deleteEdges( topo, &deledge, LWT_COL_EDGE_EDGE_ID );
+ if ( n == -1 )
+ {
+ lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
+ return -1;
+ }
+ if ( n != 1 )
+ {
+ lwerror("Unexpected error: %d edges deleted when expecting 1", n);
+ return -1;
+ }
+
+ /* TODO: notify to caller about edge being removed ?
+ * See https://trac.osgeo.org/postgis/ticket/3248
+ */
+
+ return 0; /* success */
+}
+
/* Used by _lwt_RemEdge to update edge face ref on healing
*
* @param of old face id (never 0 as you cannot remove face 0)
PG_RETURN_TEXT_P(cstring2text(buf));
}
+/* ST_RemIsoEdge(atopology, anedge) */
+Datum ST_RemIsoEdge(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_RemIsoEdge);
+Datum ST_RemIsoEdge(PG_FUNCTION_ARGS)
+{
+ text* toponame_text;
+ char buf[64];
+ char* toponame;
+ int ret;
+ LWT_ELEMID node_id;
+ LWT_TOPOLOGY *topo;
+
+ if ( PG_ARGISNULL(0) || PG_ARGISNULL(1) ) {
+ 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);
+
+ node_id = PG_GETARG_INT32(1) ;
+
+ if ( SPI_OK_CONNECT != SPI_connect() ) {
+ lwpgerror("Could not connect to SPI");
+ PG_RETURN_NULL();
+ }
+ be_data.data_changed = false;
+
+ 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_RemIsoEdge");
+ ret = lwt_RemIsoEdge(topo, node_id);
+ POSTGIS_DEBUG(1, "lwt_RemIsoEdge returned");
+ lwt_FreeTopology(topo);
+
+ if ( ret == -1 ) {
+ /* should never reach this point, as lwerror would raise an exception */
+ SPI_finish();
+ PG_RETURN_NULL();
+ }
+
+ /* TODO: check if any TopoGeometry exists including this point in
+ * its definition ! */
+
+ SPI_finish();
+
+ if ( snprintf(buf, 64, "Isolated edge " INT64_FORMAT
+ " removed", node_id) >= 64 )
+ {
+ buf[63] = '\0';
+ }
+ PG_RETURN_TEXT_P(cstring2text(buf));
+}
+
/* ST_MoveIsoNode(atopology, anode, apoint) */
Datum ST_MoveIsoNode(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(ST_MoveIsoNode);
--
CREATE OR REPLACE FUNCTION topology.ST_RemoveIsoEdge(atopology varchar, anedge integer)
RETURNS TEXT AS
-$$
-DECLARE
- edge RECORD;
- rec RECORD;
- ok BOOL;
-BEGIN
-
- --
- -- Atopology and anedge are required
- --
- IF atopology IS NULL OR anedge IS NULL THEN
- RAISE EXCEPTION
- 'SQL/MM Spatial exception - null argument';
- END IF;
-
- --
- -- Check edge existance
- --
- ok = false;
- FOR edge 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 node isolation
- --
- IF edge.left_face != edge.right_face THEN
- RAISE EXCEPTION
- 'SQL/MM Spatial exception - not isolated edge';
- END IF;
-
- FOR rec IN EXECUTE 'SELECT * FROM '
- || quote_ident(atopology) || '.edge_data '
- || ' WHERE edge_id != ' || anedge
- || ' AND ( start_node = ' || edge.start_node
- || ' OR start_node = ' || edge.end_node
- || ' OR end_node = ' || edge.start_node
- || ' OR end_node = ' || edge.end_node
- || ' ) '
- LOOP
- RAISE EXCEPTION
- 'SQL/MM Spatial exception - not isolated edge';
- END LOOP;
-
- --
- -- Delete the edge
- --
- EXECUTE 'DELETE FROM ' || quote_ident(atopology) || '.edge_data '
- || ' WHERE edge_id = ' || anedge;
-
- RETURN 'Isolated edge ' || anedge || ' removed';
-END
-$$
-LANGUAGE 'plpgsql' VOLATILE;
+ 'MODULE_PATHNAME','ST_RemIsoEdge'
+ LANGUAGE 'c' VOLATILE;
--} ST_RemoveIsoEdge
--{