[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0rc1-156-g3c622d0
git at osgeo.org
git at osgeo.org
Mon Apr 26 02:32:43 PDT 2021
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".
The branch, master has been updated
via 3c622d02437567d718b56bf336fdbe77b2e8ec0b (commit)
via fb9fa7e9ddb3eb59c7dec63a44a040b4c0e88332 (commit)
via fea3aac3989348b85c20a7e59f4d90bd83198035 (commit)
from 05eaa361c5a7745d335166bd8e8d708b22103170 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 3c622d02437567d718b56bf336fdbe77b2e8ec0b
Author: Sandro Santilli <strk at kbt.io>
Date: Mon Apr 26 11:30:34 2021 +0200
Add NEWS item
diff --git a/NEWS b/NEWS
index bfc48bc..89ff3c8 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,8 @@ PostGIS 3.2.0
- #4870, Allow open options to be passed to GDAL drivers (Paul Ramsey)
- ST_Value() accepts resample parameter to add bilinear option (Paul Ramsey)
- #3778, #4401, ST_Boundary now works for TIN and does not linearize curves (Aliaksandr Kalenik)
+ - #4881, #4884, Store sign of edge_id for lineal TopoGeometry in relation table
+ to retain direction (Sandro Santilli)
* New features*
- #4841, FindTopology to quickly get a topology record (Sandro Santilli)
@@ -20,7 +22,7 @@ PostGIS 3.2.0
using one of a number of algorithms (inverse weighted distance, average, etc)
using algorithms from GDAL
(Paul Ramsey)
- - ST_Contour() generates contour lines from raster values
+ - ST_Contour() generates contour lines from raster values
using algorithms from GDAL (Paul Ramsey)
- ST_SetZ()/ST_SetM() fills in z/m coordinates of a geometry using data read
from a raster (Paul Ramsey)
commit fb9fa7e9ddb3eb59c7dec63a44a040b4c0e88332
Author: Sandro Santilli <strk at kbt.io>
Date: Mon Apr 26 10:44:06 2021 +0200
Have TopoGeo_addLinestring return signed edge ids for lineals
Closes #4884 in main branch (3.2.0dev)
Update expected results accordingly
Add specific tests for totopogeom.
diff --git a/liblwgeom/lwgeom_topo.c b/liblwgeom/lwgeom_topo.c
index 2c7d3fd..e48bdd4 100644
--- a/liblwgeom/lwgeom_topo.c
+++ b/liblwgeom/lwgeom_topo.c
@@ -5253,9 +5253,13 @@ lwt_AddPoint(LWT_TOPOLOGY* topo, LWPOINT* point, double tol)
/* Return identifier of an equal edge, 0 if none or -1 on error
* (and lwerror gets called on error)
+ *
+ * If an equal edge is found, specify, in "forward" variable whether
+ * the edge is also equal direction-wise
+ *
*/
static LWT_ELEMID
-_lwt_GetEqualEdge( LWT_TOPOLOGY *topo, LWLINE *edge )
+_lwt_GetEqualEdge( LWT_TOPOLOGY *topo, LWLINE *edge, int *forward )
{
LWT_ELEMID id;
LWT_ISO_EDGE *edges;
@@ -5307,6 +5311,40 @@ _lwt_GetEqualEdge( LWT_TOPOLOGY *topo, LWLINE *edge )
if ( equals )
{
id = e->edge_id;
+ /* Check if direction also matches */
+ if ( forward )
+ {
+ /* If input line is closed, we use winding order */
+ if ( lwline_is_closed(edge) )
+ {
+ if ( ptarray_isccw(edge->points) == ptarray_isccw(e->geom->points) )
+ {
+ *forward = 1;
+ }
+ else
+ {
+ *forward = 0;
+ }
+ }
+ else
+ {
+ /* Input line is not closed, checking fist point is enough */
+ if (
+ memcmp(
+ getPoint_internal(edge->points, 0),
+ getPoint_internal(e->geom->points, 0),
+ sizeof(POINT2D)
+ ) == 0
+ )
+ {
+ *forward = 1;
+ }
+ else
+ {
+ *forward = 0;
+ }
+ }
+ }
GEOSGeom_destroy(edgeg);
_lwt_release_edges(edges, num);
return id;
@@ -5327,10 +5365,16 @@ _lwt_GetEqualEdge( LWT_TOPOLOGY *topo, LWLINE *edge )
* if the newly added edge would split a face and if so
* would create new faces accordingly. Otherwise it will
* set left_face and right_face to null (-1)
+ *
+ * @param forward output parameter, will be populated if
+ * a pre-existing edge was found in the topology,
+ * in which case a value of 1 means the incoming
+ * line will have the same direction of the edge,
+ * and 0 that the incomine line has opposite direction
*/
static LWT_ELEMID
_lwt_AddLineEdge( LWT_TOPOLOGY* topo, LWLINE* edge, double tol,
- int handleFaceSplit )
+ int handleFaceSplit, int *forward )
{
LWCOLLECTION *col;
LWPOINT *start_point, *end_point;
@@ -5456,7 +5500,7 @@ _lwt_AddLineEdge( LWT_TOPOLOGY* topo, LWLINE* edge, double tol,
}
/* check if the so-snapped edge _now_ exists */
- id = _lwt_GetEqualEdge ( topo, edge );
+ id = _lwt_GetEqualEdge ( topo, edge, forward );
LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
if ( id == -1 )
{
@@ -5490,7 +5534,7 @@ _lwt_AddLineEdge( LWT_TOPOLOGY* topo, LWLINE* edge, double tol,
}
/* check if the so-decimated edge _now_ exists */
- id = _lwt_GetEqualEdge ( topo, edge );
+ id = _lwt_GetEqualEdge ( topo, edge, forward );
LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
if ( id == -1 )
{
@@ -5515,6 +5559,7 @@ _lwt_AddLineEdge( LWT_TOPOLOGY* topo, LWLINE* edge, double tol,
}
lwgeom_free(tmp); /* possibly takes "edge" down with it */
+ *forward = 1;
return id;
}
@@ -5557,6 +5602,7 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
uint64_t num, numedges = 0, numnodes = 0;
uint64_t i;
GBOX qbox;
+ int forward;
*nedges = -1; /* error condition, by default */
@@ -5842,7 +5888,7 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
}
#endif
- id = _lwt_AddLineEdge( topo, lwgeom_as_lwline(g), tol, handleFaceSplit );
+ id = _lwt_AddLineEdge( topo, lwgeom_as_lwline(g), tol, handleFaceSplit, &forward );
LWDEBUGF(1, "_lwt_AddLineEdge returned %" LWTFMT_ELEMID, id);
if ( id < 0 )
{
@@ -5856,9 +5902,9 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
continue;
}
- LWDEBUGF(1, "Component %d of split line is edge %" LWTFMT_ELEMID,
- i, id);
- ids[num++] = id; /* TODO: skip duplicates */
+ LWDEBUGF(1, "Component %d of split line is %s edge %" LWTFMT_ELEMID,
+ i, forward ? "forward" : "backward", id);
+ ids[num++] = forward ? id : -id; /* TODO: skip duplicates */
}
LWDEBUGG(1, noded, "Noded before free");
diff --git a/topology/test/regress/topogeo_addlinestring_expected b/topology/test/regress/topogeo_addlinestring_expected
index d786940..9c09021 100644
--- a/topology/test/regress/topogeo_addlinestring_expected
+++ b/topology/test/regress/topogeo_addlinestring_expected
@@ -71,7 +71,7 @@ crossover|E|LINESTRING(9 20,16.2 14)
crossover|E|LINESTRING(9 14,9 18)
crossover|E|LINESTRING(9 18,9 20)
crossover_again|4
-contains|25
+contains|-25
contains|46
contains|47
contains|N||POINT(7 36)
@@ -139,7 +139,7 @@ iso_ex_2segs|28
#1650.2|N||POINT(0 0)
#1650.2|N||POINT(0 1)
#1650.2|E|LINESTRING(0 0,0 1)
-#1650.3|65
+#1650.3|-65
#1650.3|66
#1650.3|N||POINT(10 0)
#1650.3|E|LINESTRING(0 0,10 0)
diff --git a/topology/test/regress/totopogeom.sql b/topology/test/regress/totopogeom.sql
index 91bb7cf..f72d58d 100644
--- a/topology/test/regress/totopogeom.sql
+++ b/topology/test/regress/totopogeom.sql
@@ -221,6 +221,25 @@ SELECT '#3359.area.1', ST_Area(toTopoGeom('POLYGON ((0 0,1 0,1 1,0 1,0 0))'
SELECT '#3359.area.2', ST_Area(toTopoGeom('POLYGON ((0 0,1 0,1 2,0 2,0 0))'
::geometry, 'tt', 4));
+--------------------------------------------------------
+-- http://trac.osgeo.org/postgis/ticket/4884
+--------------------------------------------------------
+TRUNCATE tt.relation CASCADE;
+TRUNCATE tt.edge_data CASCADE;
+TRUNCATE tt.node CASCADE;
+DELETE FROM tt.face WHERE face_id > 0;
+SELECT '#4884.setval',
+ setval('tt.edge_data_edge_id_seq', 1, false),
+ -- face_id is intentionally set to 2
+ setval('tt.face_face_id_seq', 2, false),
+ setval('tt.node_node_id_seq', 1, false);
+SELECT '#4884.l2r', ST_AsText(toTopoGeom('LINESTRING (0 0,1 0)' ::geometry, 'tt', 3));
+SELECT '#4884.r2l', ST_AsText(toTopoGeom('LINESTRING (1 0,0 0)' ::geometry, 'tt', 3));
+
+--------------------------------------------------------
+-- Cleanups
+--------------------------------------------------------
+
DROP TABLE tt.f_coll;
DROP TABLE tt.f_areal;
DROP TABLE tt.f_lineal;
diff --git a/topology/test/regress/totopogeom_expected b/topology/test/regress/totopogeom_expected
index bda0c3a..6ba1e0a 100644
--- a/topology/test/regress/totopogeom_expected
+++ b/topology/test/regress/totopogeom_expected
@@ -49,4 +49,7 @@ tgup1.3|5|200|4
#3359.line.2|2
#3359.area.1|1
#3359.area.2|2
+#4884.setval|1|2|1
+#4884.l2r|MULTILINESTRING((0 0,1 0))
+#4884.r2l|MULTILINESTRING((1 0,0 0))
Topology 'tt' dropped
commit fea3aac3989348b85c20a7e59f4d90bd83198035
Author: Sandro Santilli <strk at kbt.io>
Date: Fri Mar 12 09:20:11 2021 +0100
Rewrite TopoGeometry::geometry cast for lineals to retain direction
Includes test
Closes #4881 in main branch (3.2.0dev)
diff --git a/topology/test/regress/geometry_cast.sql b/topology/test/regress/geometry_cast.sql
index 5e65870..6ec9d07 100644
--- a/topology/test/regress/geometry_cast.sql
+++ b/topology/test/regress/geometry_cast.sql
@@ -4,35 +4,35 @@ set client_min_messages to WARNING;
select NULL FROM createtopology('tt', 4326);
-- layer 1 is PUNTUAL
-CREATE TABLE tt.f_point(id serial);
+CREATE TABLE tt.f_point(lbl text primary key);
SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_point', 'g', 'POINT');
-- layer 2 is LINEAL
-CREATE TABLE tt.f_line(id serial);
+CREATE TABLE tt.f_line(lbl text primary key );
SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_line', 'g', 'LINE');
-- layer 3 is AREAL
-CREATE TABLE tt.f_area(id serial);
+CREATE TABLE tt.f_area(lbl text primary key);
SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_area', 'g', 'POLYGON');
-- layer 4 is MIXED
-CREATE TABLE tt.f_coll(id serial);
+CREATE TABLE tt.f_coll(lbl text primary key);
SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_coll', 'g', 'COLLECTION');
-- layer 5 is HIERARCHICAL PUNTUAL
-CREATE TABLE tt.f_hier_point(id serial);
+CREATE TABLE tt.f_hier_point(lbl text primary key);
SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_hier_point', 'g', 'POINT', 1);
-- layer 6 is HIERARCHICAL LINEAL
-CREATE TABLE tt.f_hier_line(id serial);
+CREATE TABLE tt.f_hier_line(lbl text primary key);
SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_hier_line', 'g', 'LINE', 2);
-- layer 7 is HIERARCHICAL AREAL
-CREATE TABLE tt.f_hier_area(id serial);
+CREATE TABLE tt.f_hier_area(lbl text primary key);
SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_hier_area', 'g', 'POLYGON', 3);
-- layer 8 is HIERARCHICAL MIXED
-CREATE TABLE tt.f_hier_coll(id serial);
+CREATE TABLE tt.f_hier_coll(lbl text primary key);
SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_hier_coll', 'g', 'COLLECTION', 4);
@@ -47,5 +47,80 @@ SELECT 'empty', 'hier', 'lineal', ST_AsEWKT(CreateTopoGeom('tt', 2, 6)::geometry
SELECT 'empty', 'hier', 'areal', ST_AsEWKT(CreateTopoGeom('tt', 3, 7)::geometry);
SELECT 'empty', 'hier', 'mixed', ST_AsEWKT(CreateTopoGeom('tt', 4, 8)::geometry);
+-- Cast directed lineal
+-- See https://trac.osgeo.org/postgis/ticket/4881
+
+-- Insert 3 horizontal edge going in mixed directions
+-- Odd ids: left-to-right
+-- Even ids: right-to-left
+INSERT INTO tt.node(node_id, containing_face, geom) VALUES
+( 1, NULL, 'SRID=4326;POINT(1 0)' ),
+( 2, NULL, 'SRID=4326;POINT(2 0)' ),
+( 3, NULL, 'SRID=4326;POINT(3 0)' ),
+( 4, NULL, 'SRID=4326;POINT(4 0)' )
+;
+SELECT NULL FROM setval('tt.node_node_id_seq', 3);
+INSERT INTO tt.edge(
+ edge_id, start_node, end_node,
+ next_left_edge, next_right_edge,
+ left_face, right_face,
+ geom
+)
+VALUES (
+ 1, 1, 2,
+ -2, 1,
+ 0, 0,
+ 'SRID=4326;LINESTRING(0 0, 1 0)'
+),(
+ 2, 3, 2,
+ -1, 2,
+ 0, 0,
+ 'SRID=4326;LINESTRING(2 0, 1 0)'
+),(
+ 3, 3, 4,
+ -3, 2,
+ 0, 0,
+ 'SRID=4326;LINESTRING(2 0, 3 0)'
+)
+;
+SELECT NULL FROM setval('tt.edge_data_edge_id_seq', 2);
+
+-- Insert two lines using the horizontal edge
+-- in opposite directions
+INSERT INTO tt.f_line(lbl, g) VALUES (
+ 'dir.2r', CreateTopoGeom('tt', 2, 2, '{{1,2},{-2,2},{3,2}}')
+), (
+ 'dir.2l', CreateTopoGeom('tt', 2, 2, '{{-1,2},{-3,2},{2,2}}')
+), (
+ 'dir.multi.2r', CreateTopoGeom('tt', 2, 2, '{{1,2},{3,2}}')
+), (
+ 'dir.multi.2l', CreateTopoGeom('tt', 2, 2, '{{-1,2},{-3,2}}')
+), (
+ 'dir.multi.converge', CreateTopoGeom('tt', 2, 2, '{{1,2},{-3,2}}')
+), (
+ 'dir.multi.diverge', CreateTopoGeom('tt', 2, 2, '{{-1,2},{3,2}}')
+);
+
+-- Check out lines are rendered with direction
+-- based on their signed element_id
+SELECT
+ '#4881',
+ 'E',
+ e.edge_id,
+ ST_AsText(e.geom)
+FROM tt.edge e
+ORDER BY e.edge_id;
+
+SELECT
+ '#4881',
+ l.lbl,
+ ST_AsEWKT(ST_CollectionHomogenize(l.g::geometry)),
+ array_agg(r.element_id ORDER BY abs(r.element_id))
+FROM tt.f_line l, tt.relation r
+WHERE lbl like 'dir.%'
+AND r.topogeo_id = id(l.g)
+GROUP BY 1,2,3
+ORDER BY lbl;
+
-- Cleanup
SELECT NULL FROM DropTopology('tt');
diff --git a/topology/test/regress/geometry_cast_expected b/topology/test/regress/geometry_cast_expected
index b692443..4ef94e4 100644
--- a/topology/test/regress/geometry_cast_expected
+++ b/topology/test/regress/geometry_cast_expected
@@ -6,3 +6,12 @@ empty|hier|puntal|SRID=4326;MULTIPOINT EMPTY
empty|hier|lineal|SRID=4326;MULTILINESTRING EMPTY
empty|hier|areal|SRID=4326;MULTIPOLYGON EMPTY
empty|hier|mixed|SRID=4326;GEOMETRYCOLLECTION EMPTY
+#4881|E|1|LINESTRING(0 0,1 0)
+#4881|E|2|LINESTRING(2 0,1 0)
+#4881|E|3|LINESTRING(2 0,3 0)
+#4881|dir.2l|SRID=4326;LINESTRING(3 0,2 0,1 0,0 0)|{-1,2,-3}
+#4881|dir.2r|SRID=4326;LINESTRING(0 0,1 0,2 0,3 0)|{1,-2,3}
+#4881|dir.multi.2l|SRID=4326;MULTILINESTRING((1 0,0 0),(3 0,2 0))|{-1,-3}
+#4881|dir.multi.2r|SRID=4326;MULTILINESTRING((0 0,1 0),(2 0,3 0))|{1,3}
+#4881|dir.multi.converge|SRID=4326;MULTILINESTRING((0 0,1 0),(3 0,2 0))|{1,-3}
+#4881|dir.multi.diverge|SRID=4326;MULTILINESTRING((1 0,0 0),(2 0,3 0))|{-1,3}
diff --git a/topology/topology.sql.in b/topology/topology.sql.in
index aa3383f..4f01bc0 100644
--- a/topology/topology.sql.in
+++ b/topology/topology.sql.in
@@ -1343,15 +1343,30 @@ AND element_type = 3
ELSIF topogeom.type = 2 THEN -- [multi]line -- }{
- sql :=
- 'SELECT st_multi(ST_LineMerge(ST_Collect(e.geom))) as g FROM '
- || quote_ident(toponame) || '.edge e, '
- || quote_ident(toponame) || '.relation r '
- ' WHERE r.topogeo_id = ' || topogeom.id
- || ' AND r.layer_id = ' || topogeom.layer_id
- || ' AND r.element_type = 2 '
- ' AND abs(r.element_id) = e.edge_id';
- EXECUTE sql INTO geom;
+ sql := format(
+ $$
+SELECT
+ st_multi(
+ ST_LineMerge(
+ ST_Collect(
+ CASE
+ WHEN r.element_id > 0 THEN
+ e.geom
+ ELSE
+ ST_Reverse(e.geom)
+ END
+ )
+ )
+ ) as g
+FROM %1$I.edge e, %1$I.relation r
+WHERE r.topogeo_id = id($1)
+AND r.layer_id = layer_id($1)
+AND r.element_type = 2
+AND abs(r.element_id) = e.edge_id
+ $$,
+ toponame
+ );
+ EXECUTE sql USING topogeom INTO geom;
ELSIF topogeom.type = 1 THEN -- [multi]point -- }{
-----------------------------------------------------------------------
Summary of changes:
NEWS | 4 +-
liblwgeom/lwgeom_topo.c | 62 +++++++++++++--
topology/test/regress/geometry_cast.sql | 91 ++++++++++++++++++++--
topology/test/regress/geometry_cast_expected | 9 +++
.../test/regress/topogeo_addlinestring_expected | 4 +-
topology/test/regress/totopogeom.sql | 19 +++++
topology/test/regress/totopogeom_expected | 3 +
topology/topology.sql.in | 33 +++++---
8 files changed, 197 insertions(+), 28 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list