[PostGIS] #5911: ST_ClipByBox2D shows precision issues when clipping curved geometries

PostGIS trac at osgeo.org
Wed May 28 01:51:53 PDT 2025


#5911: ST_ClipByBox2D shows precision issues when clipping curved geometries
----------------------------+---------------------------
 Reporter:  dmyzl           |      Owner:  pramsey
     Type:  defect          |     Status:  new
 Priority:  medium          |  Milestone:  PostGIS 3.5.4
Component:  postgis         |    Version:  3.5.x
 Keywords:  ST_ClipByBox2D  |
----------------------------+---------------------------
 The return value of the `ST_ClipByBox2D` function appears to be highly
 sensitive to floating-point precision. For example, consider the following
 case where a curved geometry is created and then clipped using a BOX2D
 generated from the same geometry:

 {{{
 select st_astext(ST_ClipByBox2D(
     st_geomfromtext('circularstring(0 0, 20 20, 1 0)', 4369), -- curve
     box2d(st_geomfromtext('circularstring(0 0, 20 20, 1 0)', 4369)) --
 curve's box2d
 ));
 }}}

 I think the result should be identical to the original curve, since the
 bounding box is derived from the geometry itself. However, the actual
 output is a clipped version of the curve:

 {{{
 -- expected:
 CIRCULARSTRING(0 0,20 20,1 0)

 -- actually return:
 LINESTRING(0 0,-0.956217377487237 0.048022441162846,-1.908926599762526
 0.14290640005694,-2.855832506861942 0.28442329291445,-3.794653919516114
 0.472232193145072,-4.723129134710917 0.705880652658024,-5.63902137432812
 0.984805791849158,-6.540124173739798 1.308335655627204,-7.424266697374892
 1.675690832212453,-8.289318968452221 2.085986330807994,-9.133197000281127
 2.538233713620073,-9.953867816767952 3.031343477091301,-10.749354350033514
 3.564127676610166,-11.517740203342775
 4.135302788373643,-12.257174267872456
 4.743492801508452,-12.965875182194335
 5.387232533001804,-13.642135623730946 6.064971157455592,-14.28432642184521
 6.775075943160619,-14.89090048265519 7.515836185490278,-15.460396516118793
 8.285467328137871,-15.991442556409432
 9.082115262269028,-16.482759267101912
 9.903860793232306,-16.933163023205918
 10.748724264067215,-17.341568762622284
 11.614670324671216,-17.70699260015264
 12.499612835136393,-18.028554197765015
 13.401419891443219,-18.305478885405304
 14.317918961404084,-18.537099527245235
 15.246902118483618,-18.722858128871056
 16.18613136088711,-18.86230718154091 17.133344003102838,-18.95511074027262
 18.086258126909666,-19.00104523316457 19.04257807871793,-19
 19.999999999999993,-18.951977558837154
 20.956217377487235,-18.85709359994306
 21.908926599762534,-18.715576707085546
 22.855832506861944,-18.52776780685493
 23.794653919516115,-18.294119347341976
 24.723129134710913,-18.015194208150845
 25.63902137432811,-17.691664344372796
 26.540124173739798,-17.324309167787547
 27.424266697374897,-16.914013669192006
 28.28931896845222,-16.461766286379927
 29.13319700028113,-15.968656522908699
 29.953867816767954,-15.435872323389837
 30.749354350033506,-14.864697211626357
 31.517740203342775,-14.25650719849155
 32.25717426787246,-13.612767466998196
 32.96587518219434,-12.935028842544408
 33.642135623730944,-12.224924056839388
 34.28432642184521,-11.484163814509717 34.8909004826552,-10.714532671862129
 35.46039651611879,-9.917884737730974 35.99144255640943,-9.096139206767694
 36.48275926710191,-8.251275735932785 36.93316302320592,-7.385329675328776
 37.34156876262229,-6.500387164863607 37.70699260015264,-5.598580108556783
 38.02855419776502,-4.682081038595918 38.30547888540531,-3.753097881516383
 38.53709952724523,-2.813868639112898 38.72285812887105,-1.866655996897162
 38.86230718154091,-0.913741873090335 38.955110740272616,0.04257807871793
 39.001045233164575,0.999999999999992 39,1.956217377487226
 38.95197755883716,2.908926599762533 38.857093599943056,3.855832506861944
 38.715576707085546,4.794653919516112 38.52776780685493,5.723129134710911
 38.294119347341976,6.63902137432811 38.015194208150845,7.540124173739804
 37.691664344372796,8.424266697374893 37.32430916778755,9.28931896845222
 36.914013669192,10.133197000281125 36.46176628637993,10.95386781676795
 35.9686565229087,11.749354350033506 35.43587232338984,12.517740203342772
 34.86469721162636,13.257174267872454 34.25650719849155,13.965875182194333
 33.6127674669982,14.642135623730944 32.93502884254441,15.284326421845204
 32.224924056839384,15.890900482655184 31.484163814509728,16.46039651611879
 30.71453267186213,16.99144255640943 29.917884737730972,17.482759267101912
 29.096139206767695,17.933163023205918 28.251275735932786,18.34156876262228
 27.38532967532879,18.70699260015263 26.500387164863625,19.028554197765015
 25.598580108556785,19.305478885405304
 24.682081038595918,19.537099527245235
 23.753097881516382,19.722858128871056 22.8138686391129,19.86230718154091
 21.86665599689718,19.95511074027262 20.913741873090338,20.00104523316457
 19.957421921282073,20 19.00000000000001,19.951977558837154
 18.043782622512776,19.857093599943063 17.091073400237487,19.71557670708555
 16.144167493138056,19.527767806854932 15.205346080483888,19.29411934734198
 14.27687086528909,19.015194208150845 13.36097862567189,18.6916643443728
 12.459875826260213,18.324309167787547
 11.575733302625107,17.914013669192006
 10.710681031547782,17.461766286379927 9.866802999718875,16.9686565229087
 9.04613218323205,16.435872323389837 8.250645649966497,15.86469721162637
 7.482259796657241,15.25650719849155 6.742825732127546,14.612767466998198
 6.034124817805667,13.93502884254441 5.357864376269056,13.22492405683939
 4.715673578154796,12.484163814509733 4.109099517344816,11.71453267186213
 3.539603483881208,10.917884737730978 3.008557443590568,10.096139206767695
 2.517240732898088,9.251275735932788 2.066836976794082,8.385329675328794
 1.65843123737772,7.500387164863626 1.293007399847369,6.598580108556786
 0.971445802234985,5.68208103859592 0.694521114594696,4.753097881516386
 0.462900472754765,3.813868639112901 0.277141871128944,2.866655996897182
 0.13769281845909,1.913741873090338 0.04488925972738,1 0)
 }}}

 Upon further inspection, the center of the arc lies at `(0.5, 19.5)`, and
 its radius is approximately `19.00640920313115955764`. The bounding box
 returned by Box2D appears to slightly underestimate the maximum x value:

 {{{
 select st_astext(
     box2d(st_geomfromtext('circularstring(0 0, 20 20, 1 0)', 4369))
 );

 -- return:
 POLYGON((-19.00640920313116 0,-19.00640920313116
 39.006409203131156,20.00640920313116 39.006409203131156,20.00640920313116
 0,-19.00640920313116 0))
 }}}

 To account for this, I tried slightly enlarging the bounding box in all
 dimensions to ensure it fully contained the curve, but the result was
 still not as expected. I continued adjusting the box until I increased or
 decreased the fifth decimal place of the bounding box's min/max
 coordinates — only then did the function return the expected result:

 {{{
 select st_astext(ST_ClipByBox2D(
     st_geomfromtext('circularstring(0 0, 20 20, 1 0)', 4369),
     st_geomfromtext('POLYGON((-19.00640920313116
 -0.00640920313116,-19.00640920313116 39.00640920313116,20.00640920313116
 39.00640920313116,20.00640920313116 -0.00640920313116,-19.00640920313116
 -0.00640920313116))', 4369)
         )
 );
 -- return:
 -- (The very long result above)

 select st_astext(ST_ClipByBox2D(
     st_geomfromtext('circularstring(0 0, 20 20, 1 0)', 4369),
     st_geomfromtext('POLYGON((-19.00641 -0.00641,-19.00641
 39.00641,20.00641 39.00641,20.00641 -0.00641,-19.00641 -0.00641))', 4369)
 ));
 -- return:
 -- (The very long result above)

 select st_astext(ST_ClipByBox2D(
     st_geomfromtext('circularstring(0 0, 20 20, 1 0)', 4369),
     st_geomfromtext('POLYGON((-19.00642 -0.00642,-19.00642
 39.00642,20.00642 39.00642,20.00642 -0.00642,-19.00642 -0.00642))', 4369)
 ));
 -- return:
 -- CIRCULARSTRING(0 0,20 20,1 0)
 }}}

 I'm not sure if this level of sensitivity to floating-point precision is
 expected behavior for this function.

 postgis_full_version:

 {{{
 POSTGIS="3.5.3 0" [EXTENSION] PGSQL="170" GEOS="3.13.1-CAPI-1.19.2"
 SFCGAL="SFCGAL 1.5.0, CGAL 5.6, BOOST 1.74.0" PROJ="9.3.1
 NETWORK_ENABLED=OFF URL_ENDPOINT=https://cdn.proj.org
 USER_WRITABLE_DIRECTORY=/home/yzl/.local/share/proj
 DATABASE_PATH=/home/yzl/project/build_pg_postgis/proj-9.3.1/tmp_install/share/proj/proj.db"
 (compiled against PROJ 9.3.1) GDAL="GDAL 3.7.2, released 2023/09/05"
 LIBXML="2.9.13" LIBJSON="0.17" LIBPROTOBUF="1.3.3" WAGYU="0.5.0
 (Internal)" (core procs from "3.5.2 dea6d0a" need upgrade) TOPOLOGY
 (topology procs from "3.5.2 dea6d0a" need upgrade) RASTER (raster procs
 from "3.5.2 dea6d0a" need upgrade) (sfcgal procs from "3.5.2 dea6d0a" need
 upgrade)
 }}}
-- 
Ticket URL: <https://trac.osgeo.org/postgis/ticket/5911>
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