Recentemente me deparei com um problema onde tinha quatro círculos (pontos médios e raio) e tive que calcular a área de união desses círculos.
Imagem de exemplo:
Para dois círculos é muito fácil,
Posso apenas calcular a fração da área de cada círculo que não está dentro dos triângulos e depois calcular a área dos triângulos.
Mas existe um algoritmo inteligente que posso usar quando há mais de dois círculos?
Respostas:
Encontre todas as interseções do círculo no perímetro externo (por exemplo, B, D, F, H no diagrama a seguir). Conecte-os com os centros dos círculos correspondentes para formar um polígono. A área da união dos círculos é a área do polígono + a área das fatias do círculo definidas por pontos de intersecção consecutivos e o centro do círculo entre eles. Você também precisará levar em consideração quaisquer buracos.
fonte
Tenho certeza de que existe um algoritmo inteligente, mas aqui está um burro para evitar que você tenha que procurá-lo;
Claro que é idiota, mas:
fonte
A resposta das formigas Aasma deu a ideia básica, mas eu queria torná-la um pouco mais concreta. Dê uma olhada nos cinco círculos abaixo e como eles foram decompostos.
Identificar esses 3 tipos de pontos é fácil. Agora construa uma estrutura de dados de gráfico onde os nós são os pontos azuis e os pontos vermelhos com interior branco. Para cada círculo, coloque uma aresta entre o meio do círculo (ponto azul) e cada uma de suas interseções (pontos vermelhos com interior branco) em seu limite.
Isso decompõe a união do círculo em um conjunto de polígonos (sombreado em azul) e pedaços de pizza circulares (sombreado em verde) que são separados por pares e cobrem a união original (ou seja, uma partição). Como cada peça aqui é algo fácil de calcular a área de, você pode calcular a área da união somando as áreas das peças.
fonte
Para uma solução diferente da anterior, você poderia produzir uma estimativa com uma precisão arbitrária usando uma quadtree.
Isso também funciona para qualquer união de forma se você puder dizer se um quadrado está dentro ou fora ou cruza a forma.
Cada célula tem um dos estados: vazio, cheio, parcial
O algoritmo consiste em "desenhar" os círculos da quadtree a partir de uma resolução baixa (4 células por exemplo marcadas como vazias). Cada célula é:
Quando terminar, você pode calcular uma estimativa da área: as células cheias fornecem o limite inferior, as células vazias fornecem o limite superior, as células parciais fornecem o erro de área máximo.
Se o erro for muito grande para você, refine as células parciais até obter a precisão correta.
Acho que isso será mais fácil de implementar do que o método geométrico que pode exigir o tratamento de muitos casos especiais.
fonte
Eu amo a abordagem do caso de 2 círculos que se cruzam - aqui está como eu usaria uma ligeira variação da mesma abordagem para o exemplo mais complexo.
Isso pode fornecer uma visão melhor sobre a generalização do algoritmo para um número maior de círculos semi-sobrepostos.
A diferença aqui é que eu começo ligando os centros (então há um vértice entre o centro dos círculos, em vez de entre os lugares onde os círculos se cruzam). Acho que isso permite generalizar melhor.
(na prática, talvez o método monte-carlo valha a pena)
(fonte: secretGeek.net )
fonte
Se você quiser uma resposta discreta (em oposição a contínua), pode fazer algo semelhante a um algoritmo de pintura de pixel.
Desenhe os círculos em uma grade e, em seguida, pinte cada célula da grade se estiver contida principalmente em um círculo (ou seja, pelo menos 50% de sua área está dentro de um dos círculos). Faça isso para a grade inteira (onde a grade abrange toda a área coberta pelos círculos) e, em seguida, conte o número de células coloridas na grade.
fonte
Hmm, problema muito interessante. Minha abordagem provavelmente seria algo como o seguinte:
(isso é verdadeiro para qualquer forma, seja círculo ou outro)
Onde
A ∪ B
significa A união B eA ∩ B
significa A intersecção B (você pode resolver isso desde a primeira etapa.(Este é o mesmo que acima, onde
A
foi substituído porA∪B
)Onde
area(A∪B)
acabamos de trabalhar earea((A∪B)∩C)
pode ser encontrado:Onde novamente você pode encontrar a área (A∩B∩C) de cima.
A parte complicada é a última etapa - quanto mais círculos são adicionados, mais complexo ele se torna. Acredito que haja uma expansão para calcular a área de uma interseção com uma união finita ou, alternativamente, você pode resolvê-la recursivamente.
Ainda com relação ao uso de Monte-Carlo para aproximar a área de itersecção, acredito que seja possível reduzir a intersecção de um número arbitrário de círculos para a intersecção de 4 desses círculos, que pode ser calculado exatamente (não tenho ideia de como fazer isso Contudo).
Provavelmente há uma maneira melhor de fazer isso aliás - a complexidade aumenta significativamente (possivelmente exponencialmente, mas não tenho certeza) para cada círculo extra adicionado.
fonte
Tenho trabalhado em um problema de simulação de campos estelares sobrepostos, tentando estimar as verdadeiras contagens de estrelas a partir das áreas reais do disco em campos densos, onde as estrelas maiores brilhantes podem mascarar as mais fracas. Eu também esperava ser capaz de fazer isso por meio de uma análise formal rigorosa, mas não consegui encontrar um algoritmo para a tarefa. Resolvi isso gerando os campos estelares em um fundo azul como discos verdes, cujo diâmetro foi determinado por um algoritmo de probabilidade. Uma rotina simples pode emparelhá-los para ver se há uma sobreposição (tornando o par de estrelas amarelo); então, uma contagem de pixels das cores gera a área observada para comparar com a área teórica. Isso então gera uma curva de probabilidade para as contagens verdadeiras. Força bruta talvez, mas parece funcionar bem. (fonte: 2from.com )
fonte
Este é um algoritmo que deve ser fácil de implementar na prática e pode ser ajustado para produzir erros arbitrariamente pequenos:
As etapas 2 e 3 podem ser realizadas usando algoritmos padrão e fáceis de encontrar da geometria computacional.
Obviamente, quanto mais lados você usar para cada polígono aproximado, mais perto da exata sua resposta estará. Você pode aproximar usando polígonos inscritos e circunscritos para obter os limites da resposta exata.
fonte
Existem soluções eficientes para esse problema usando o que são conhecidos como diagramas de energia. Esta é uma matemática realmente pesada e não algo que eu gostaria de resolver de imediato. Para uma solução "fácil", procure algoritmos de varredura de linha. O princípio básico aqui é que você divida a figura em tiras, onde calcular a área em cada tira é relativamente fácil.
Assim, na figura que contém todos os círculos sem nada apagado, desenhe uma linha horizontal em cada posição que é o topo de um círculo, a parte inferior de um círculo ou a intersecção de 2 círculos. Observe que, dentro dessas faixas, todas as áreas que você precisa calcular têm a mesma aparência: um "trapézio" com dois lados substituídos por segmentos circulares. Portanto, se você conseguir descobrir como calcular essa forma, basta fazer isso para todas as formas individuais e adicioná-las. A complexidade dessa abordagem ingênua é O (N ^ 3), onde N é o número de círculos na figura. Com algum uso inteligente da estrutura de dados, você poderia melhorar este método de varredura de linha para O (N ^ 2 * log (N)), mas a menos que seja realmente necessário, provavelmente não vale a pena se dar ao trabalho.
fonte
Achei este link que pode ser útil. Porém, não parece haver uma resposta definitiva. Respostas do Google . Outra referência para três círculos é o teorema de Haruki . Também há um jornal lá.
fonte
Dependendo do problema que você está tentando resolver, pode ser suficiente obter um limite superior e inferior. Um limite superior é fácil, apenas a soma de todos os círculos. Para um limite inferior, você pode escolher um único raio de forma que nenhum dos círculos se sobreponha. Para melhor isso, encontre o maior raio (até o raio real) para cada círculo de forma que ele não se sobreponha. Também deve ser bastante trivial remover quaisquer círculos completamente sobrepostos (Todos esses círculos satisfazem | P_a - P_b | <= r_a) onde P_a é o centro do círculo A, P_b é o centro do círculo B e r_a é o raio de A ) e isso melhora o limite superior e inferior. Você também pode obter um Limite superior melhor se usar sua fórmula de par em pares arbitrários, em vez de apenas a soma de todos os círculos. Pode haver uma boa maneira de escolher o "melhor"
Dados os limites superior e inferior, você pode ajustar melhor uma abordagem de Monte-carlo, mas nada específico vem à mente. Outra opção (novamente dependendo de seu aplicativo) é rasterizar os círculos e contar pixels. É basicamente a abordagem de Monte-carlo com uma distribuição fixa.
fonte
Isso pode ser resolvido usando o Teorema de Green , com uma complexidade de n ^ 2log (n). Se você não está familiarizado com o Teorema de Green e deseja saber mais, aqui está o vídeo e as notas da Khan Academy. Mas, para o bem de nosso problema, acho que minha descrição será suficiente.
Equação Geral do Teorema de Green
Se eu colocar L e M de forma que
Doença
então o RHS é simplesmente a área da Região R e pode ser obtido resolvendo a integral fechada ou LHS e isso é exatamente o que vamos fazer.
Todos os sindicatos podem ser divididos em conjuntos desconexos de círculos que se cruzam
Portanto, a integração ao longo do caminho no sentido anti-horário nos dá a Área da região e a integração ao longo do sentido horário nos dá o negativo da Área . assim
AreaOfUnion = (Integração ao longo de arcos vermelhos no sentido anti-horário + Integração ao longo de arcos azuis no sentido horário)
Mas o truque legal é se, para cada círculo, se integrarmos os arcos que não estão dentro de nenhum outro círculo, obtermos nossa área necessária, ou seja, obtermos integração no sentido anti-horário ao longo de todos os arcos vermelhos e integração ao longo de todos os arcos azuis ao longo do sentido horário. TAREFA CONCLUÍDA!!!
Aqui está o link do GitHub para meu código C ++
fonte
A abordagem de pintura de pixels (conforme sugerido por @Loadmaster) é superior à solução matemática de várias maneiras:
A única desvantagem da pintura em pixels é a precisão finita da solução. Mas isso é ajustável simplesmente renderizando para telas maiores ou menores conforme a situação exigir. Observe também que o anti-aliasing no código de renderização 2D (geralmente ativado por padrão) renderá uma precisão melhor do que o nível de pixel. Então, por exemplo, renderizar uma figura 100x100 em uma tela com as mesmas dimensões deve, eu acho, produzir uma precisão da ordem de 1 / (100 x 100 x 255) = 0,000039% ... o que provavelmente é "bom o suficiente" para todos, exceto os problemas mais exigentes.
fonte