Pelo contrário, o tempo é previsível. É proporcional à proporção da área de extensão do polígono dividida pela área do polígono, vezes o tempo necessário para gerar e testar um único ponto. O tempo varia um pouco, mas a variação é proporcional à raiz quadrada do número de pontos. Para números grandes, isso se torna inconseqüente. Divida os polígonos tortuosos em pedaços mais compactos, se necessário, para reduzir esse índice de área a um valor baixo. Apenas polígonos fractais lhe causam problemas, mas duvido que você os tenha!
@ Pablo: boas descobertas. No entanto, ambas as perguntas são específicas software e ambos preocupação colocando matrizes regulares de pontos dentro de polígonos, os pontos não aleatórios
whuber
Concordo com a diferença entre whuber e pontos aleatórios versus geração regular de pontos em um polígono.
Mapperz
Respostas:
20
Comece decompondo o polígono em triângulos e gere pontos dentro deles . (Para uma distribuição uniforme, pese cada triângulo pela sua área.)
+1 Simples e eficaz. Vale ressaltar que pontos aleatoriamente uniformes podem ser gerados dentro de um triângulo sem nenhuma rejeição, porque existem mapeamentos (facilmente computáveis) de preservação de área entre qualquer triângulo e um triângulo retângulo isósceles, que é meio quadrado, digamos o meio onde a coordenada y excede a coordenada x. Gere duas coordenadas aleatórias e classifique-as para obter um ponto aleatório no triângulo isósceles e depois mapeie-o de volta ao triângulo original.
whuber
+1 Gosto muito da discussão de coordenadas trilineares mencionadas no artigo que você cita. Suponho que isso seria passível de esfera cuja superfície é representada como um mosaico de triângulos. Em um plano projetado, não seria uma distribuição verdadeiramente aleatória, seria?
22611 Kirk Kuykendall
@whuber - +1 de volta para você. Outra maneira (no link, mas eles acenaram com a mão) é refletir os pontos rejeitados do quadrilátero uniformemente amostrado através da borda compartilhada e de volta ao triângulo.
Dan S.
@Kirk - o link de citação é um pouco anti-útil, pois lista vários métodos de amostragem errados (não uniformes), incluindo coordenadas trilineares, antes do caminho "certo". Não parece haver uma maneira direta de obter uma amostragem uniforme com coordenadas trilineares. Eu abordaria a amostragem uniforme em toda a esfera convertendo vetores de unidades aleatórias em 3d para seus equivalentes lat / lon, mas sou apenas eu. (. Incerto sobre amostragem restrita a esférica triângulos / polígonos) (também inseguro sobre amostragem verdadeiramente uniforme sobre, por exemplo WGS84: ângulos apenas escolher vai viés um pouco em direção aos pólos, eu acho.)
Dan S.
1
@ Dan Para amostrar uniformemente a esfera, use uma projeção cilíndrica de área igual (as coordenadas são longitude e cosseno de latitude). Se você quiser amostrar sem usar uma projeção, há um belo truque: gere três variáveis normais padrão independentes (x, y, z) e projete-as no ponto (R x / n, Ry / n, R * z / n ) onde n ^ 2 = x ^ 2 + y ^ 2 + z ^ 2 e R é o raio da terra. Converta para (lat, lon), se necessário (usando latitudes autálicas ao trabalhar em um esferóide). Funciona porque essa distribuição normal trivariada é esfericamente simétrica. Para amostrar triângulos, mantenha uma projeção.
whuber
14
Ao colocar uma tag QGIS nesta pergunta: A ferramenta Random Points pode ser usada com uma camada de limite.
Se você estiver procurando por código, o código-fonte do plug-in subjacente deve ser útil.
Você pode determinar a extensão do polígono e restringir a geração de números aleatórios para os valores X e Y dentro dessas extensões.
Processo básico: 1) Determine maxx, maxy, minx, miny de vértices poligonais, 2) Gere pontos aleatórios usando esses valores como limites 3) Teste cada ponto para interseção com seu polígono, 4) Interrompa a geração quando houver pontos suficientes que satisfaçam a interseção teste
Aqui está um algoritmo (C #) para o teste de interseção:
Se R é uma opção, veja ?spsampleno sppacote. Os polígonos podem ser lidos em qualquer formato suportado pelo GDAL embutido no pacote rgdal e, em seguida, spsampletrabalha diretamente no objeto importado com uma variedade de opções de amostragem.
+1 - Como R é de código aberto, se alguém deseja replicar, você sempre pode acessar o código-fonte para ver como eles são feitos. Para padrões de pontos, também pode estar interessado nas ferramentas de simulação no pacote spatstat.
Andy W
5
Eu gostaria de oferecer uma solução que requer muito pouco em termos de análise GIS. Em particular, ele não requer triangulação de polígonos.
O algoritmo a seguir, fornecido no pseudocódigo, refere-se a algumas operações simples, além dos recursos básicos de manipulação de lista (criar, encontrar comprimento, anexar, classificar, extrair sublistas e concatenar) e geração de flutuações aleatórias no intervalo [0, 1):
Area:Return the area of a polygon (0for an empty polygon).BoundingBox:Return the bounding box (extent) of a polygon.Width:Return the width of a rectangle.Height:Return the height of a rectangle.Left:Split a rectangle into two halves andreturn the left half.Right:... returning the right half.Top:... returning the top half.Bottom:... returning the bottom half.Clip:Clip a polygon to a rectangle.RandomPoint:Return a random point in a rectangle.Search:Search a sorted list for a target value.Return the index
of the last element less than the target.In:Test whether a point is inside a polygon.
Eles estão disponíveis em quase todos os ambientes de GIS ou de programação gráfica (e fáceis de codificar, se não). Clipnão deve retornar polígonos degenerados (ou seja, aqueles com área zero).
O procedimento SimpleRandomSampleobtém com eficiência uma lista de pontos distribuídos aleatoriamente em um polígono. É um invólucro para SRS, que quebra o polígono em pedaços menores até que cada peça seja suficientemente compacta para ser amostrada com eficiência. Para fazer isso, ele usa uma lista pré-computada de números aleatórios para decidir quantos pontos alocar para cada peça.
O SRS pode ser "ajustado" alterando o parâmetro t. Essa é a proporção máxima da caixa delimitadora: área do polígono que pode ser tolerada. Se o tamanho for pequeno (mas maior que 1), a maioria dos polígonos será dividida em várias partes; torná-lo grande pode fazer com que muitos pontos de teste sejam rejeitados em alguns polígonos (sinuosos, com lascas ou cheios de orifícios). Isso garante que o tempo máximo para amostrar o polígono original é previsível.
ProcedureSimpleRandomSample(P:Polygon, N:Integer){
U =Sorted list of N independent uniform values between 0and1Return SRS(P,BoundingBox(P), U)}
O próximo procedimento chama a si próprio recursivamente, se necessário. A expressão misteriosa t*N + 5*Sqrt(t*N)estima conservadoramente um limite superior de quantos pontos serão necessários, respondendo pela variabilidade do acaso. A probabilidade de que isso falhe é de apenas 0,3 por milhão de chamadas de procedimento. Aumente 5 para 6 ou até 7 para reduzir essa probabilidade, se quiser.
Procedure SRS(P:Polygon, B:Rectangle, U:List){
N =Length(U)If(N ==0){Return empty list}
aP =Area(P)If(aP <=0){Error("Cannot sample degenerate polygons.")Return empty list}
t =2If(aP*t <Area(B)){# Cut P into piecesIf(Width(B)>Height(B)){
B1 =Left(B); B2 =Right(B)}Else{
B1 =Bottom(B); B2 =Top(B)}
P1 =Clip(P, B1); P2 =Clip(P, B2)
K =Search(U,Area(P1)/ aP)
V =Concatenate( SRS(P1, B1, U[1::K]), SRS(P2, B2, U[K+1::N]))}Else{# Sample P
V = empty list
maxIter = t*N +5*Sqrt(t*N)While(Length(V)< N and maxIter >0){Decrement maxIter
Q =RandomPoint(B)If(Q In P){Append Q to V}}If(Length(V)< N){Error("Too many iterations.")}}Return V}
Se seu polígono é convexo e você conhece todos os vértices, considere fazer uma ponderação convexa "aleatória" dos vértices para provar um novo ponto que é garantido que fica dentro do casco convexo (neste caso, polígono).
Por exemplo, digamos que você tenha um polígono convexo em N lados com vértices
V_i, i={1,..,N}
Gere aleatoriamente pesos N convexos
w_1,w_2,..,w_N such that ∑ w_i =1; w_i>=0
O ponto amostrado aleatoriamente é então dado por
Y=∑ w_i*V_i
Pode haver uma maneira diferente de amostrar pesos convexos N
Escolha números N-1 uniformemente aleatoriamente dentro de um intervalo (sem substituição), ordene-os e normalize os intervalos N entre eles para obter os pesos.
Você também pode obter amostras da distribuição Dirichlet, que é frequentemente usada como um conjugado anterior para a distribuição multinomial, que é semelhante aos pesos convexos no seu caso.
Quando o polígono não é muito severamente não convexo, considere primeiro convertê-lo em um casco convexo. Isso deve pelo menos limitar o número de pontos fora do polígono em grande parte.
A tarefa é muito fácil de resolver no GRASS GIS (um comando) usando o v.random .
Abaixo um exemplo de como adicionar 3 pontos aleatórios em polígonos selecionados (aqui áreas de CEP da cidade de Raleigh, NC) na página de manual. Modificando a instrução "where" do SQL, os polígonos podem ser selecionados.
Claro: os códigos postais fazem referência a agências postais específicas e suas rotas de entrega de correio. Como resultado, os códigos postais são linhas, não polígonos. Eles podem se sobrepor, conter buracos e não necessariamente cobrir todo o país ou qualquer estado. Usá-los para dividir a área é perigoso por esse motivo. As unidades de censo (como grupos de blocos) são uma escolha melhor. Veja também: isto e isto .
Richard
1
Obrigado! Provavelmente também depende do país; veja, por exemplo, en.wikipedia.org/wiki/Postal_codes_in_Alemanha - no entanto, os CEPs não são o meu tópico principal, apenas querem ilustrar e responder à pergunta original "Gere pontos que estão dentro do polígono" em vez de discutir ZIP definições de código que é OT aqui :-)
markusN
1
Observado em ambas as contagens. Eu provavelmente deveria fazer um pouco de entrada de blog para que eu possa dizer isto na próxima vez tudo de forma mais sucinta :-)
Aqui está uma abordagem simples e melhor, usando a distância real das coordenadas da direção xey. O algoritmo interno usa o WGS 1984 (4326) e a transformação de resultado no SRID inserido.
Segunda função baseada no algoritmo Nicklas Avén . Já tentei lidar com qualquer SRID.
Eu apliquei após as alterações no algoritmo.
Variável separada para direção x e y para tamanho de pixel,
Nova variável para calcula a distância em esferóide ou elipsóide.
Insira qualquer SRID, função transforme Geom no ambiente de trabalho do Spheroid ou Ellipsoid Datum, aplique a distância em cada lado, obtenha o resultado e transforme na entrada SRID.
Respostas:
Comece decompondo o polígono em triângulos e gere pontos dentro deles . (Para uma distribuição uniforme, pese cada triângulo pela sua área.)
fonte
Ao colocar uma tag QGIS nesta pergunta: A ferramenta Random Points pode ser usada com uma camada de limite.
Se você estiver procurando por código, o código-fonte do plug-in subjacente deve ser útil.
fonte
Você pode determinar a extensão do polígono e restringir a geração de números aleatórios para os valores X e Y dentro dessas extensões.
Processo básico: 1) Determine maxx, maxy, minx, miny de vértices poligonais, 2) Gere pontos aleatórios usando esses valores como limites 3) Teste cada ponto para interseção com seu polígono, 4) Interrompa a geração quando houver pontos suficientes que satisfaçam a interseção teste
Aqui está um algoritmo (C #) para o teste de interseção:
fonte
Existem algumas boas bibliotecas por aí que fazem a maior parte do trabalho pesado para você.
Exemplo usando [shapely] [1] em python.
Ou use
.representative_point()
para obter um ponto dentro do objeto (como mencionado por dain):fonte
representative_point
método: shapely.readthedocs.io/en/latest/…Se R é uma opção, veja
?spsample
nosp
pacote. Os polígonos podem ser lidos em qualquer formato suportado pelo GDAL embutido no pacote rgdal e, em seguida,spsample
trabalha diretamente no objeto importado com uma variedade de opções de amostragem.fonte
Eu gostaria de oferecer uma solução que requer muito pouco em termos de análise GIS. Em particular, ele não requer triangulação de polígonos.
O algoritmo a seguir, fornecido no pseudocódigo, refere-se a algumas operações simples, além dos recursos básicos de manipulação de lista (criar, encontrar comprimento, anexar, classificar, extrair sublistas e concatenar) e geração de flutuações aleatórias no intervalo [0, 1):
Eles estão disponíveis em quase todos os ambientes de GIS ou de programação gráfica (e fáceis de codificar, se não).
Clip
não deve retornar polígonos degenerados (ou seja, aqueles com área zero).O procedimento
SimpleRandomSample
obtém com eficiência uma lista de pontos distribuídos aleatoriamente em um polígono. É um invólucro paraSRS
, que quebra o polígono em pedaços menores até que cada peça seja suficientemente compacta para ser amostrada com eficiência. Para fazer isso, ele usa uma lista pré-computada de números aleatórios para decidir quantos pontos alocar para cada peça.O SRS pode ser "ajustado" alterando o parâmetro
t
. Essa é a proporção máxima da caixa delimitadora: área do polígono que pode ser tolerada. Se o tamanho for pequeno (mas maior que 1), a maioria dos polígonos será dividida em várias partes; torná-lo grande pode fazer com que muitos pontos de teste sejam rejeitados em alguns polígonos (sinuosos, com lascas ou cheios de orifícios). Isso garante que o tempo máximo para amostrar o polígono original é previsível.O próximo procedimento chama a si próprio recursivamente, se necessário. A expressão misteriosa
t*N + 5*Sqrt(t*N)
estima conservadoramente um limite superior de quantos pontos serão necessários, respondendo pela variabilidade do acaso. A probabilidade de que isso falhe é de apenas 0,3 por milhão de chamadas de procedimento. Aumente 5 para 6 ou até 7 para reduzir essa probabilidade, se quiser.fonte
Se seu polígono é convexo e você conhece todos os vértices, considere fazer uma ponderação convexa "aleatória" dos vértices para provar um novo ponto que é garantido que fica dentro do casco convexo (neste caso, polígono).
Por exemplo, digamos que você tenha um polígono convexo em N lados com vértices
Gere aleatoriamente pesos N convexos
O ponto amostrado aleatoriamente é então dado por
Pode haver uma maneira diferente de amostrar pesos convexos N
Quando o polígono não é muito severamente não convexo, considere primeiro convertê-lo em um casco convexo. Isso deve pelo menos limitar o número de pontos fora do polígono em grande parte.
fonte
A tarefa é muito fácil de resolver no GRASS GIS (um comando) usando o v.random .
Abaixo um exemplo de como adicionar 3 pontos aleatórios em polígonos selecionados (aqui áreas de CEP da cidade de Raleigh, NC) na página de manual. Modificando a instrução "where" do SQL, os polígonos podem ser selecionados.
fonte
Link de resposta
https://gis.stackexchange.com/a/307204/103524
Três algoritmos usando abordagens diferentes.
Git Repo Link
Função =================================================== ==================
Use a função com uma consulta simples, a geometria deve ser válida e polígono, multi-polígonos ou envelope
SELECT I_Grid_Point_Distance(geom, 50, 61) from polygons limit 1;
Resultado =================================================== =====================
Segunda função baseada no algoritmo Nicklas Avén . Já tentei lidar com qualquer SRID.
Eu apliquei após as alterações no algoritmo.
Função =================================================== ==================
Use-o com uma consulta simples.
SELECT I_Grid_Point(geom, 22, 15, false) from polygons;
Resultado =================================================== ==================
Função =================================================== =================
Use-o com uma consulta simples.
SELECT I_Grid_Point_Series(geom, 22, 15, false) from polygons;
Resultado =================================================== =========================fonte