Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

215
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda