[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0rc1-93-g5363724

git at osgeo.org git at osgeo.org
Thu Feb 18 08:44:24 PST 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  5363724d5d1c1cbc1bf6eb3c42c18b970c192c14 (commit)
      from  4312d040ff9ef255bc3bac58068753b0422dfd23 (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 5363724d5d1c1cbc1bf6eb3c42c18b970c192c14
Author: Sandro Santilli <strk at kbt.io>
Date:   Mon Feb 15 16:09:11 2021 +0100

    Implement TopoGeom_addTopoGeom(tgt TopoGeometry, src TopoGeometry)
    
    Closes #4851
    
    Includes regression tests, documentation and NEWS entry

diff --git a/NEWS b/NEWS
index 741ad29..bcb4d2a 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ PostGIS 3.2.0
 
  * New features*
   - #4841, FindTopology to quickly get a topology record (Sandro Santilli)
+  - #4851, TopoGeom_addTopoGeom function (Sandro Santilli)
 
 PostGIS 3.1.0
 2020/12/18
diff --git a/doc/extras_topology.xml b/doc/extras_topology.xml
index 574fa6e..8e60a77 100644
--- a/doc/extras_topology.xml
+++ b/doc/extras_topology.xml
@@ -3250,6 +3250,65 @@ UPDATE mylayer SET tg = TopoGeom_remElement(tg, '{43,3}');
 			</refsection>
 		</refentry>
 
+    <refentry id="TopoGeom_addTopoGeom">
+			<refnamediv>
+				<refname>TopoGeom_addTopoGeom</refname>
+				<refpurpose>Adds element of a TopoGeometry to the definition of another TopoGeometry.</refpurpose>
+			</refnamediv>
+			<refsynopsisdiv>
+				<funcsynopsis>
+					<funcprototype>
+					<funcdef>topogeometry <function>TopoGeom_addTopoGeom</function></funcdef>
+					<paramdef><type>topogeometry </type> <parameter>tgt</parameter></paramdef>
+                    <paramdef><type>topogeometry </type> <parameter>src</parameter></paramdef>
+					</funcprototype>
+				</funcsynopsis>
+			</refsynopsisdiv>
+
+			<refsection>
+                <title>Description</title>
+
+                <para>
+Adds the elements of a <xref linkend="topogeometry" /> to the definition of
+another TopoGeometry, possibly changing its cached type (type attribute)
+to a collection, if needed to hold all elements in the source object.
+                </para>
+
+                <para>
+The two TopoGeometry objects need be defined against the *same*
+topology and, if hierarchically defined, need be composed by elements
+of the same child layer.
+                </para>
+
+                <!-- use this format if new function -->
+                <para>Availability: 3.2</para>
+			</refsection>
+			<refsection>
+				<title>Examples</title>
+        <programlisting>
+-- Set an "overall" TopoGeometry value to be composed by all
+-- elements of specific TopoGeometry values
+UPDATE mylayer SET tg_overall = TopoGeom_addTopogeometry(
+    TopoGeom_addTopoGeometry(
+        clearTopoGeom(tg_overall),
+        tg_specific1
+    ),
+    tg_specific1
+);
+				</programlisting>
+			</refsection>
+
+			<!-- Optionally add a "See Also" section -->
+			<refsection>
+				<title>See Also</title>
+        <para>
+<xref linkend="TopoGeom_addElement" />,
+<xref linkend="clearTopoGeom" />,
+<xref linkend="CreateTopoGeom" />
+        </para>
+			</refsection>
+		</refentry>
+
     <refentry id="toTopoGeom_editor_proxy">
 			<refnamediv>
         <refname>toTopoGeom</refname>
diff --git a/topology/sql/topogeometry/topogeom_edit.sql.in b/topology/sql/topogeometry/topogeom_edit.sql.in
index 0889bb7..6b93bf8 100644
--- a/topology/sql/topogeometry/topogeom_edit.sql.in
+++ b/topology/sql/topogeometry/topogeom_edit.sql.in
@@ -93,3 +93,129 @@ END
 $$
 LANGUAGE 'plpgsql' VOLATILE STRICT;
 -- }
+
+
+-- {
+-- Add the component of a TopoGeometry to the definition of
+-- another TopoGeometry.
+--
+-- The two TopoGeometry objects need to be defined on the *same*
+-- topology and need to be compatible (both simple or built over
+-- the same child layer, and the target TopoGeometry needs to allow
+-- for holding components of the type found in the source TopoGeometry)
+--
+-- }{
+CREATE OR REPLACE FUNCTION topology.TopoGeom_addTopoGeom(tgt topology.TopoGeometry, src topology.TopoGeometry)
+  RETURNS topology.TopoGeometry
+AS
+$BODY$
+DECLARE
+  sql TEXT;
+  topo topology.topology;
+  srcElementTypes int[];
+  srcLayer topology.layer;
+  tgtLayer topology.layer;
+  maxElemType int;
+BEGIN
+
+  -- Get topology information
+  topo := topology.FindTopology(topology_id(src));
+
+#ifdef POSTGIS_TOPOLOGY_DEBUG
+  RAISE DEBUG 'Source TopoGeometry is "%", its topology_id is "%"', src, topo.id;
+#endif
+
+  IF topology_id(src) != topology_id(tgt) THEN
+    RAISE EXCEPTION 'Source and target TopoGeometry objects need be defined on the same topology';
+  END IF;
+
+#ifdef POSTGIS_TOPOLOGY_DEBUG
+  RAISE DEBUG 'Target TopoGeometry is "%"', tgt;
+#endif
+
+  SELECT * FROM topology.layer
+  WHERE topology_id = topo.id
+    AND layer_id = layer_id(src)
+  INTO srcLayer;
+
+  SELECT * FROM topology.layer
+  WHERE topology_id = topo.id
+    AND layer_id = layer_id(tgt)
+  INTO tgtLayer;
+
+  -- Check simple/hierarchical compatibility
+  IF srcLayer.child_id IS NULL THEN
+    IF srcLayer.child_id IS NOT NULL THEN
+      RAISE EXCEPTION 'Cannot add components of hierarchical TopoGeometry to a non-hierarchical TopoGeometry';
+    END IF;
+  ELSIF tgtLayer.child_id IS NULL THEN
+      RAISE EXCEPTION 'Cannot add components of non-hierarchical TopoGeometry to a hierarchical TopoGeometry';
+  ELSIF tgtLayer.child_id != srcLayer.childId THEN
+      RAISE EXCEPTION 'Cannot add components of hierarchical TopoGeometry to a hierarchical TopoGeometry based on different layer';
+  END IF;
+
+  -- Add every element of the source TopoGeometry to
+  -- the definition of the target TopoGeometry
+  sql := format($$
+WITH inserted AS (
+  INSERT INTO %1$I.relation(
+    topogeo_id,
+    layer_id,
+    element_id,
+    element_type
+  )
+  SELECT %2$s, %3$s, element_id, element_type
+  FROM %1$I.relation
+  WHERE topogeo_id = %4$L
+  AND layer_id = %5$L
+  EXCEPT
+  SELECT %2$s, %3$s, element_id, element_type
+  FROM %1$I.relation
+  WHERE topogeo_id = %2$L
+  AND layer_id = %3$L
+  RETURNING element_type
+)
+SELECT array_agg(DISTINCT element_type) FROM inserted
+    $$,
+    topo.name,      -- %1
+    id(tgt),        -- %2
+    layer_id(tgt),  -- %3
+    id(src),        -- %4
+    layer_id(src)   -- %5
+  );
+
+  RAISE DEBUG 'SQL: %', sql;
+
+  EXECUTE sql INTO srcElementTypes;
+
+  -- TODO: Check layer's feature_type compatibility ?
+  -- or let the relationTrigger take care of it ?
+--  IF tgtLayer.feature_type != 4 THEN -- 'mixed' typed target can accept anything
+--    IF srcLayer.feature_type != tgtLayer.feature_type THEN
+--    END IF;
+--  END IF;
+
+  RAISE DEBUG 'Target type: %', type(tgt);
+  RAISE DEBUG 'Detected source element types: %', srcElementTypes;
+
+  -- Check if target TopoGeometry type needs be changed
+  IF type(tgt) != 4 -- collection TopoGeometry accept anything
+  THEN
+    IF array_upper(srcElementTypes, 1) > 1
+    OR srcElementTypes[1] != tgt.type
+    THEN
+      -- source is mixed-typed or typed differently from
+      -- target, so we turn target type to collection
+      RAISE DEBUG 'Changing target element type to collection';
+      tgt.type = 4;
+    END IF;
+  END IF;
+
+
+
+
+  RETURN tgt;
+END
+$BODY$
+LANGUAGE 'plpgsql' VOLATILE STRICT;
+-- }
diff --git a/topology/test/regress/topogeom_addtopogeom.sql b/topology/test/regress/topogeom_addtopogeom.sql
new file mode 100644
index 0000000..59e630b
--- /dev/null
+++ b/topology/test/regress/topogeom_addtopogeom.sql
@@ -0,0 +1,81 @@
+\set VERBOSITY terse
+set client_min_messages to WARNING;
+
+
+--------------------------------------------------------
+-- See https://trac.osgeo.org/postgis/ticket/4851
+--------------------------------------------------------
+
+select NULL FROM createtopology('tt');
+
+-- Create simple puntal layer (will be layer 1)
+CREATE TABLE tt.f_puntal(id serial);
+SELECT 'simple_puntual_layer', AddTopoGeometryColumn('tt', 'tt', 'f_puntal','g','POINT');
+
+-- Create a lineal layer (will be layer 2)
+CREATE TABLE tt.f_lineal(id serial);
+SELECT 'simple_lineal_layer', AddTopoGeometryColumn('tt', 'tt', 'f_lineal','g','LINE');
+
+-- Create an areal layer (will be layer 3)
+CREATE TABLE tt.f_areal(id serial);
+SELECT 'simple_areal_layer', AddTopoGeometryColumn('tt', 'tt', 'f_areal','g','POLYGON');
+
+-- Create a collection layer (will be layer 4)
+CREATE TABLE tt.f_coll(id serial);
+SELECT 'simple_collection_layer', AddTopoGeometryColumn('tt', 'tt', 'f_coll','g','COLLECTION');
+
+-- Create a hierarchical puntal layer (will be layer 5)
+CREATE TABLE tt.f_hier_puntal(id serial);
+SELECT 'hierarchical_puntual_layer', AddTopoGeometryColumn('tt', 'tt', 'f_hier_puntal','g','POINT', 1);
+
+
+-- point to point
+SELECT 'tg2tg.poi2poi', ST_AsText(TopoGeom_addTopoGeom(
+    toTopoGeom('POINT(1 1)', 'tt', 1),
+    toTopoGeom('POINT(0 0)', 'tt', 1)
+));
+
+-- point to mixed
+SELECT 'tg2tg.poi2mix', ST_AsText(TopoGeom_addTopoGeom(
+    toTopoGeom('LINESTRING(1 1, 0 0)', 'tt', 4),
+    toTopoGeom('POINT(0 0)', 'tt', 1)
+));
+
+-- line to line
+SELECT 'tg2tg.lin2lin', ST_AsText(TopoGeom_addTopoGeom(
+    toTopoGeom('LINESTRING(0 1, 2 1)', 'tt', 2),
+    toTopoGeom('LINESTRING(0 0, 2 0)', 'tt', 2)
+));
+
+-- line to mixed
+SELECT 'tg2tg.lin2mix', ST_AsText(TopoGeom_addTopoGeom(
+    toTopoGeom('POINT(0 0)', 'tt', 4),
+    toTopoGeom('LINESTRING(0 0, 2 0)', 'tt', 2)
+));
+
+-- poly to poly
+SELECT 'tg2tg.pol2pol', ST_AsText(ST_Simplify(ST_Normalize(TopoGeom_addTopoGeom(
+    toTopoGeom(ST_MakeEnvelope(0,10,20,10), 'tt', 3),
+    toTopoGeom(ST_MakeEnvelope(0,0,10,10), 'tt', 3)
+)::geometry), 0));
+
+-- poly to mixed
+SELECT 'tg2tg.pol2pol', ST_AsText(ST_Simplify(ST_Normalize(TopoGeom_addTopoGeom(
+    toTopoGeom(ST_MakePoint(0,0), 'tt', 4),
+    toTopoGeom(ST_MakeEnvelope(0,0,10,10), 'tt', 4)
+)::geometry), 0));
+
+-- TODO: point to point (hierarchical)
+-- TODO: point to mixed (hierarchical)
+-- TODO: line to line (hierarchical)
+-- TODO: line to mixed (hierarchical)
+-- TODO: poly to poly (hierarchical)
+-- TODO: poly to mixed (hierarchical)
+-- TODO: BOGUS calls (incompatible merges)
+
+DROP TABLE tt.f_coll;
+DROP TABLE tt.f_areal;
+DROP TABLE tt.f_lineal;
+DROP TABLE tt.f_hier_puntal;
+DROP TABLE tt.f_puntal;
+select NULL from droptopology('tt');
diff --git a/topology/test/regress/topogeom_addtopogeom_expected b/topology/test/regress/topogeom_addtopogeom_expected
new file mode 100644
index 0000000..1abdecc
--- /dev/null
+++ b/topology/test/regress/topogeom_addtopogeom_expected
@@ -0,0 +1,11 @@
+simple_puntual_layer|1
+simple_lineal_layer|2
+simple_areal_layer|3
+simple_collection_layer|4
+hierarchical_puntual_layer|5
+tg2tg.poi2poi|MULTIPOINT(0 0,1 1)
+tg2tg.poi2mix|GEOMETRYCOLLECTION(LINESTRING(1 1,0 0),POINT(0 0))
+tg2tg.lin2lin|MULTILINESTRING((0 0,2 0),(0 1,1 1,2 1))
+tg2tg.lin2mix|GEOMETRYCOLLECTION(LINESTRING(0 0,2 0),POINT(0 0))
+tg2tg.pol2pol|MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))
+tg2tg.pol2pol|GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0)),POINT(0 0))
diff --git a/topology/test/regress/totopogeom.sql b/topology/test/regress/totopogeom.sql
index 9d93521..91bb7cf 100644
--- a/topology/test/regress/totopogeom.sql
+++ b/topology/test/regress/totopogeom.sql
@@ -1,5 +1,5 @@
 \set VERBOSITY terse
-set client_min_messages to ERROR;
+set client_min_messages to WARNING;
 
 select 'create', createtopology('tt') > 0;
 
@@ -199,7 +199,9 @@ SELECT 'tgup1.3', id(t.g), st_area(t.g), count(r.*)
   WHERE t.id = -1 AND r.layer_id = 4 AND r.topogeo_id = id(t.g)
   GROUP BY id(t.g), st_area(t.g);
 
+--------------------------------------------------------
 -- http://trac.osgeo.org/postgis/ticket/3359
+--------------------------------------------------------
 -- NOTE: requires identifier of the second edge to be 2
 TRUNCATE tt.relation CASCADE;
 TRUNCATE tt.edge_data CASCADE;
diff --git a/topology/test/tests.mk b/topology/test/tests.mk
index fa4025f..be7cf85 100644
--- a/topology/test/tests.mk
+++ b/topology/test/tests.mk
@@ -59,6 +59,7 @@ TESTS += \
 	$(topsrcdir)/topology/test/regress/topogeo_addpoint.sql \
 	$(topsrcdir)/topology/test/regress/topogeo_addpolygon.sql \
   $(topsrcdir)/topology/test/regress/topogeom_edit.sql \
+  $(topsrcdir)/topology/test/regress/topogeom_addtopogeom.sql \
 	$(topsrcdir)/topology/test/regress/topogeometry_type.sql \
 	$(topsrcdir)/topology/test/regress/topojson.sql \
   $(topsrcdir)/topology/test/regress/topologysummary.sql \

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                               |   1 +
 doc/extras_topology.xml                            |  59 ++++++++++
 topology/sql/topogeometry/topogeom_edit.sql.in     | 126 +++++++++++++++++++++
 topology/test/regress/topogeom_addtopogeom.sql     |  81 +++++++++++++
 .../test/regress/topogeom_addtopogeom_expected     |  11 ++
 topology/test/regress/totopogeom.sql               |   4 +-
 topology/test/tests.mk                             |   1 +
 7 files changed, 282 insertions(+), 1 deletion(-)
 create mode 100644 topology/test/regress/topogeom_addtopogeom.sql
 create mode 100644 topology/test/regress/topogeom_addtopogeom_expected


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list