Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

206
Views
PostGIS testing if point intersects scaled polygon sometimes gets wrong answer

I need an algorithm where I can check if a point falls within a polygon within a small tolerance (meaning the point is completely within the polygon or sufficiently close to the border). To implement this, I was planning on using the st_scale function to expand the polygon by a factor, then check the point with st_within. Note that I can't use st_buffer because st_buffer expects an absolute radius of the buffer but I need a relative radius (ex. Determine if the point is within the polygon or within the polygon that has been scaled up by 5%).

To accomplish this, I've written the following tester code. I take a polygon, scale it up by 5%, and then test to see if the original polygon's centroid falls within the scaled-up polygon:

SELECT ST_within(
  st_centroid(polygon),
  st_scale(
    polygon,
    'POINT(1.05 1.05)'::geometry,
    st_centroid(polygon)
));

However, sometimes this function fails for no apparent reason (meaning it says the polygon's centroid is not within the scaled-up polygon) and I have no idea why. This feels like it's buggy, but I can't imagine I've found a bug in postGIS.

Passing testcases:

-- drawing a 1x1 box at the origin of the x-y plane
SELECT ST_Within(
  st_centroid('MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)))'::geometry),
  st_scale(
    'MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)))'::geometry,
    'POINT(1.05 1.05)'::geometry,
    st_centroid('MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)))'::geometry))
);

-- box in the first quadrant at an origin of (10, 10)
SELECT ST_Within(
  st_centroid('MULTIPOLYGON(((10 10, 11 10, 11 11, 10 11, 10 10)))'::geometry),
  st_scale(
    'MULTIPOLYGON(((10 10, 11 10, 11 11, 10 11, 10 10)))'::geometry,
    'POINT(1.05 1.05)'::geometry,
    st_centroid('MULTIPOLYGON(((10 10, 11 10, 11 11, 10 11, 10 10)))'::geometry))
);

Failing testcase:

-- 1x1 box with the bottom left corner at (98, 28)
SELECT ST_within(
  st_centroid('MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry),
  st_scale(
    'MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry,
    'POINT(1.05 1.05)'::geometry,
    st_centroid('MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry))
);

Interestingly, though, casting the scaled shape to WKT and then back to a geometry DOES work.

-- 1x1 box with the bottom left corner at (98, 28)
SELECT ST_within(
  st_centroid('MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry),
  st_geomfromewkt(st_asewkt(st_scale(
    'MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry,
    'POINT(1.05 1.05)'::geometry,
    st_centroid('MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry))))
);

So, yeah, what is going on here???? Have I found a bug in PostGIS?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

I think you've found a bug in older versions of postgis. I used docker and some servers to test with several versions of postgres and postgis. With version 3.1.4 the code works properly.

In the past I've stumbled in some corner cases were postgis gave unexpected results. Those were related to GEOS, that according to the manual is the library that implements the ST_Within function, but in this case the GEOS library is the same in all tests.

From what your working query that transforms to ewkt and back shows, this should be related with an internal operation in postgis that got corrected. I tried but did not find a bug that I could relate to this.

I post two of the tests that I've done:

postgres 12, postgis 3.0.0

The bug is present:

test=# select postgis_full_version();
                                                                                              postgis_full_version                                                                                              
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 POSTGIS="3.0.0 r17983" [EXTENSION] PGSQL="120" GEOS="3.7.1-CAPI-1.11.1 27a5e771" PROJ="Rel. 5.2.0, September 15th, 2018" LIBXML="2.9.4" LIBJSON="0.12.1" LIBPROTOBUF="1.3.1" WAGYU="0.4.3 (Internal)" TOPOLOGY
(1 row)

test=# SELECT ST_within(
  st_centroid('MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry),
  st_scale(
    'MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry,
    'POINT(1.05 1.05)'::geometry,
    st_centroid('MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry))
);
 st_within 
-----------
 f
(1 row)

postgres 13, postgis 3.1.4

The code works as expected:

test=# select postgis_full_version();
                                                                                              postgis_full_version                                                                                               
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 POSTGIS="3.1.4 ded6c34" [EXTENSION] PGSQL="130" GEOS="3.7.1-CAPI-1.11.1 27a5e771" PROJ="Rel. 5.2.0, September 15th, 2018" LIBXML="2.9.4" LIBJSON="0.12.1" LIBPROTOBUF="1.3.1" WAGYU="0.5.0 (Internal)" TOPOLOGY
(1 row)

test=# SELECT ST_within(
  st_centroid('MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry),
  st_scale(
    'MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry,
    'POINT(1.05 1.05)'::geometry,
    st_centroid('MULTIPOLYGON(((98 28,99 28,99 29,98 29,98 28)))'::geometry))
);
 st_within 
-----------
 t
(1 row)
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!