{"id":7290,"date":"2018-09-06T11:15:51","date_gmt":"2018-09-06T14:15:51","guid":{"rendered":"http:\/\/www.fernandoquadro.com.br\/html\/?p=7290"},"modified":"2018-09-06T11:15:51","modified_gmt":"2018-09-06T14:15:51","slug":"divisao-de-poligonos-no-postgis","status":"publish","type":"post","link":"https:\/\/www.fernandoquadro.com.br\/html\/2018\/09\/06\/divisao-de-poligonos-no-postgis\/","title":{"rendered":"Divis\u00e3o de pol\u00edgonos no PostGIS"},"content":{"rendered":"<p>Uma das coisas interessantes do processamento geoespacial \u00e9 a variedade de ferramentas, e as maneiras de coloc\u00e1-las juntas podem produzir resultados surpreendentes.<\/p>\n<p>Um membro da comunidade na lista de usu\u00e1rios do PostGIS perguntou: \u201cExiste uma maneira de dividir um pol\u00edgono em subpol\u00edgonos de \u00e1reas mais ou menos iguais?\u201d<\/p>\n<p>O desenvolvedor do PostGIS, <a href=\"https:\/\/github.com\/komzpa\" rel=\"noopener\" target=\"_blank\">Darafei Praliaskouski<\/a>, respondeu e forneceu uma <a href=\"https:\/\/lists.osgeo.org\/pipermail\/postgis-users\/2018-June\/042795.html\" rel=\"noopener\" target=\"_blank\">solu\u00e7\u00e3o funcional<\/a> que \u00e9 absolutamente brilhante ao combinar as partes do kit de ferramentas do PostGIS para resolver um problema bastante complicado. Ele disse:<\/p>\n<blockquote><p>\nDo jeito que eu vejo, para qualquer tipo de pol\u00edgono:<\/p>\n<ul>\n<li> Converte um pol\u00edgono em um conjunto de pontos proporcionais \u00e0 \u00e1rea por ST_GeneratePoints (quanto mais pontos, mais bonito ser\u00e1, acho que 1000 est\u00e1 ok); <\/li>\n<li> Decida quantas partes voc\u00ea gostaria de dividir em (ST_Area (geom) \/ max_area), seja K; <\/li>\n<li> Para cada cluster, pegue um ST_Centroid (ST_Collect (point)); <\/li>\n<li> Alimente esses centr\u00f3ides em ST_VoronoiPolygons, que lhe dar\u00e1 uma m\u00e1scara para cada parte do pol\u00edgono;<\/li>\n<li> Com o ST_Intersection do pol\u00edgono original e cada c\u00e9lula dos pol\u00edgonos de Voronoi voc\u00ea obter\u00e1 uma boa divis\u00e3o do seu pol\u00edgono em K partes.<\/li>\n<\/ul>\n<\/blockquote>\n<p>Vamos dar um passo de cada vez para ver como funciona.<\/p>\n<p>Usaremos o Peru como pol\u00edgono de exemplo, ele tem uma boa concavidade, o que o torna um pouco mais complicado do que um pol\u00edgono com &#8220;forma comum&#8221;.<\/p>\n<pre>\r\nCREATE TABLE peru AS \r\n  SELECT *\r\n  FROM countries\r\n  WHERE name = 'Peru'\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-0.jpg\" alt=\"\" width=\"638\" height=\"444\" class=\"aligncenter size-full wp-image-7295\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-0.jpg 638w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-0-300x209.jpg 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-0-600x418.jpg 600w\" sizes=\"auto, (max-width: 638px) 100vw, 638px\" \/><\/p>\n<p>Agora crie um campo de pontos que preencha o pol\u00edgono. Em m\u00e9dia, cada ponto colocado aleatoriamente acaba \u201cocupando\u201d uma \u00e1rea igual dentro do pol\u00edgono.<\/p>\n<pre>\r\nCREATE TABLE peru_pts AS\r\n  SELECT (ST_Dump(ST_GeneratePoints(geom, 2000))).geom AS geom\r\n  FROM peru\r\n  WHERE name = 'Peru'\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-1.jpg\" alt=\"\" width=\"635\" height=\"440\" class=\"aligncenter size-full wp-image-7296\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-1.jpg 635w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-1-300x208.jpg 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-1-600x416.jpg 600w\" sizes=\"auto, (max-width: 635px) 100vw, 635px\" \/><\/p>\n<p>Agora, agrupe o campo de pontos, definindo o n\u00famero de clusters para o n\u00famero de partes em que voc\u00ea deseja dividir o pol\u00edgono. Visualmente, agora voc\u00ea pode ver as divis\u00f5es no pol\u00edgono! Mas ainda precisamos obter linhas reais para representar essas divis\u00f5es.<\/p>\n<pre>\r\nCREATE TABLE peru_pts_clustered AS\r\n  SELECT geom, ST_ClusterKMmeans(geom, 10) over () AS cluster\r\n  FROM peru_pts;\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-2.jpg\" alt=\"\" width=\"636\" height=\"443\" class=\"aligncenter size-full wp-image-7298\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-2.jpg 636w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-2-300x209.jpg 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-2-600x418.jpg 600w\" sizes=\"auto, (max-width: 636px) 100vw, 636px\" \/><\/p>\n<p>Primeiro, calcule o centroide de cada cluster de pontos, que ser\u00e1 o centro de massa de cada cluster.<\/p>\n<pre>\r\nCREATE TABLE peru_centers AS\r\n  SELECT cluster, ST_Centroid(ST_collect(geom)) AS geom\r\n  FROM peru_pts_clustered\r\n  GROUP BY cluster;\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-3.jpg\" alt=\"\" width=\"637\" height=\"444\" class=\"aligncenter size-full wp-image-7299\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-3.jpg 637w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-3-300x209.jpg 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-3-600x418.jpg 600w\" sizes=\"auto, (max-width: 637px) 100vw, 637px\" \/><\/p>\n<p>Agora, use um diagrama de voronoi para obter arestas de divis\u00e3o reais entre os centr\u00f3ides do cluster, que acabam combinando de perto com os locais onde os clusters se dividem!<\/p>\n<pre>\r\nCREATE TABLE peru_voronoi AS\r\n  SELECT (ST_Dump(ST_VoronoiPolygons(ST_collect(geom)))).geom AS geom\r\n  FROM peru_centers;\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-4.jpg\" alt=\"\" width=\"637\" height=\"440\" class=\"aligncenter size-full wp-image-7300\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-4.jpg 637w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-4-300x207.jpg 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-4-600x414.jpg 600w\" sizes=\"auto, (max-width: 637px) 100vw, 637px\" \/><\/p>\n<p>Finalmente, intercepte as \u00e1reas de voronoi com o pol\u00edgono original para obter os pol\u00edgonos de sa\u00edda final que incorporam as bordas externas das linhas de divis\u00e3o.<\/p>\n<pre>\r\nCREATE TABLE peru_divided AS\r\n  SELECT ST_Intersection(a.geom, b.geom) AS geom\r\n  FROM peru a\r\n  CROSS JOIN peru_voronoi b;\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-5.jpg\" alt=\"\" width=\"638\" height=\"442\" class=\"aligncenter size-full wp-image-7301\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-5.jpg 638w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-5-300x208.jpg 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-5-600x416.jpg 600w\" sizes=\"auto, (max-width: 638px) 100vw, 638px\" \/><\/p>\n<p>Feito!<\/p>\n<p>Agrupar um campo de pontos para obter \u00e1reas praticamente iguais e, em seguida, usar o voronoi para extrair linhas divis\u00f3rias reais s\u00e3o insights maravilhosos sobre o processamento espacial. A imagem final de todos os componentes do c\u00e1lculo tamb\u00e9m \u00e9 bonita.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-6.jpg\" alt=\"\" width=\"634\" height=\"440\" class=\"aligncenter size-full wp-image-7302\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-6.jpg 634w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-6-300x208.jpg 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2018\/09\/poly-split-6-600x416.jpg 600w\" sizes=\"auto, (max-width: 634px) 100vw, 634px\" \/><\/p>\n<p>N\u00e3o tenho 100% de certeza, mas talvez seja poss\u00edvel usar a t\u00e9cnica de Darafei para subdivis\u00f5es ainda mais interessantes, como \u201cmapa do Brasil subdividido em \u00e1reas de igual PIB\u201d, ou \u201cmapa de S\u00e3o Paulo subdividido em \u00e1reas de igual tamanho\u201d, ou ainda a popula\u00e7\u00e3o \u201dgerando o campo de ponto inicial usando uma pondera\u00e7\u00e3o econ\u00f4mica ou demogr\u00e1fica&#8221;.<\/p>\n<p><em>Este texto foi traduzido e adaptado do post original de Paul Ramsey no blog Clever Elephant.<\/em><\/p>\n<p>Fonte: <a href=\"http:\/\/blog.cleverelephant.ca\/2018\/06\/polygon-splitting.html\" rel=\"noopener\" target=\"_blank\">Blog Clever Elephant<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Uma das coisas interessantes do processamento geoespacial \u00e9 a variedade de ferramentas, e as maneiras de coloc\u00e1-las juntas podem produzir resultados surpreendentes. Um membro da comunidade na lista de usu\u00e1rios do PostGIS perguntou: \u201cExiste uma maneira de dividir um pol\u00edgono&#8230; <a class=\"more-link\" href=\"https:\/\/www.fernandoquadro.com.br\/html\/2018\/09\/06\/divisao-de-poligonos-no-postgis\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":275,"featured_media":7305,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24],"tags":[212],"class_list":["post-7290","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gis","tag-postgis"],"_links":{"self":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/7290","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/users\/275"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/comments?post=7290"}],"version-history":[{"count":7,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/7290\/revisions"}],"predecessor-version":[{"id":7306,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/7290\/revisions\/7306"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/media\/7305"}],"wp:attachment":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/media?parent=7290"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/categories?post=7290"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/tags?post=7290"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}