[postgis-tickets] [PostGIS] #5392: Aggregate ST_Union fails to join some "circles" when radius is too large

PostGIS trac at osgeo.org
Wed May 31 06:10:17 PDT 2023


#5392: Aggregate ST_Union fails to join some "circles" when radius is too large
---------------------+---------------------------
 Reporter:  rotten   |      Owner:  pramsey
     Type:  defect   |     Status:  new
 Priority:  medium   |  Milestone:  PostGIS 3.3.3
Component:  postgis  |    Version:  3.3.x
 Keywords:           |
---------------------+---------------------------
 PostGIS 3.3.2 on PostgreSQL 14.7

 Using ST_Buffer to create two "Circles" from arbitrary points on the
 globe, and then using ST_Union as an aggregate function to combine them
 will fail when the radius exceeds some value (slightly different depending
 on where the points are on the globe).

 I've tried to make these examples as simple as I can.

 For example, this case works:
 {{{
 -- radius <= 290085 good
 with kpc as (
     select
         ST_Buffer(
             ST_Point(-166.9324011::float8, 65.154889::float8,
 4326)::geography,
             290085::integer
         )::geometry as location
 ),
 tonga as (
     select
         ST_Buffer(
             ST_Point(-177.2519031::float8, -18.5973127::float8,
 4326)::geography,
             290085::integer
         )::geometry as location
 ),
 all_circles as (
     select location from kpc
     union all
     select location from tonga
 ),
 joined_circles as (
     select
         ST_Union(location) as circle_pair
     from
         all_circles
 )
 select
     290085::integer as radius,
     ST_Distance(
         ST_Point(-166.9324011::float8, 65.154889::float8,
 4326)::geography,
         ST_Point(-177.2519031::float8, -18.5973127::float8,
 4326)::geography
     ) as kpc_tonga_distance,
     ST_AsEWKT(circle_pair)
 from
     joined_circles
 ;
 }}}

 However, if I increase the radius one more meter, it fails:
 {{{
 -- radius >= 290086 bad
 with kpc as (
     select
         ST_Buffer(
             ST_Point(-166.9324011::float8, 65.154889::float8,
 4326)::geography,
             290086::integer
         )::geometry as location
 ),
 tonga as (
     select
         ST_Buffer(
             ST_Point(-177.2519031::float8, -18.5973127::float8,
 4326)::geography,
             290086::integer
         )::geometry as location
 ),
 all_circles as (
     select location from kpc
     union all
     select location from tonga
 ),
 joined_circles as (
     select
         ST_Union(location) as circle_pair
     from
         all_circles
 )
 select
     290086::integer as radius,
     ST_Distance(
         ST_Point(-166.9324011::float8, 65.154889::float8,
 4326)::geography,
         ST_Point(-177.2519031::float8, -18.5973127::float8,
 4326)::geography
     ) as kpc_tonga_distance,
     ST_AsEWKT(circle_pair)
 from
     joined_circles
 ;
 }}}
 This is the error message:
 > psql:st_union_issue.sql:77: ERROR:  lwgeom_unaryunion_prec: GEOS Error:
 TopologyException: side location conflict at -174.563034509468
 -18.071220344085667. This can occur if the input geometry is invalid.


 Even though I know that ST_Buffer emitted valid geometries (I was able to
 check this with ST_IsValid), if I add a `ST_MakeValid` to the query that
 just failed, it works:

 {{{
 -- ST_MakeValid fixes it, even though the individual circles are valid
 with kpc as (
     select
         ST_Buffer(
             ST_Point(-166.9324011::float8, 65.154889::float8,
 4326)::geography,
             290086::integer
         )::geometry as location
 ),
 tonga as (
     select
         ST_Buffer(
             ST_Point(-177.2519031::float8, -18.5973127::float8,
 4326)::geography,
             290086::integer
         )::geometry as location
 ),
 all_circles as (
     select location from kpc
     union all
     select location from tonga
 ),
 joined_circles as (
     select
         ST_Union(ST_MakeValid(location)) as circle_pair
     from
         all_circles
 )
 select
     290086::integer as radius,
     ST_Distance(
         ST_Point(-166.9324011::float8, 65.154889::float8,
 4326)::geography,
         ST_Point(-177.2519031::float8, -18.5973127::float8,
 4326)::geography
     ) as kpc_tonga_distance,
     ST_AsEWKT(circle_pair)
 from
     joined_circles
 ;
 }}}

 Interestingly, if I don't use ST_Union as an Aggregate function, I don't
 need ST_MakeValid to get the joined circles to work.
 {{{
 -- non aggregate union fixes it
 with kpc as (
     select
         ST_Buffer(
             ST_Point(-166.9324011::float8, 65.154889::float8,
 4326)::geography,
             290086::integer
         )::geometry as location
 ),
 tonga as (
     select
         ST_Buffer(
             ST_Point(-177.2519031::float8, -18.5973127::float8,
 4326)::geography,
             290086::integer
         )::geometry as location
 ),
 joined_circles as (
     select
         ST_Union(kpc.location, tonga.location) as circle_pair
     from
         kpc, tonga
 )
 select
     290086::integer as radius,
     ST_Distance(
         ST_Point(-166.9324011::float8, 65.154889::float8,
 4326)::geography,
         ST_Point(-177.2519031::float8, -18.5973127::float8,
 4326)::geography
     ) as kpc_tonga_distance,
     ST_AsEWKT(circle_pair)
 from
     joined_circles
 ;
 }}}

 Note that the circles are not yet overlapping when they fail.  It also
 doesn't seem to matter if they cross the international date line.  Radius
 seems to be the key determinant as to when a joined pair of circles will
 start failing.

 It also doesn't matter how many segments I add to the circles.  The radius
 failing threshold for any two points remains the same.
-- 
Ticket URL: <https://trac.osgeo.org/postgis/ticket/5392>
PostGIS <http://trac.osgeo.org/postgis/>
The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project.


More information about the postgis-tickets mailing list