Encontre o melhor ajuste mais próximo para o círculo


12

Abaixo está um exemplo de imagem, se eu tiver um ponto do ponto branco no meio e desejar encontrar o local mais próximo possível do círculo azul (que obviamente está no local em que o coloquei), se todos os círculos vermelhos já existirem . Como posso encontrar esse local?

O desempenho para mim não é uma grande preocupação para este aplicativo.

insira a descrição da imagem aqui


1
qual é o significado do círculo preto? você pode colocar o círculo azul sobre ele?
Ewan

2
Portanto, para ficar claro, você deseja o local onde pode colocar o círculo azul, de modo que seja a menor distância possível do ponto branco, sem sobrepor nenhum dos outros círculos?
Robert Harvey


2
Todos os círculos sempre tocam em outro círculo em pelo menos um lugar?
Robert Harvey

Respostas:


4

Esta não é uma solução geral, pois há várias situações em que não fornecerá a posição do círculo azul a menor distância do ponto branco. Por exemplo, se você tiver 100 bolas vermelhas agrupadas e o ponto branco estiver longe desse grupo de bolas vermelhas, nenhuma delas terá influência na posição do círculo azul que pode ser centralizada no ponto branco . Nem mostrará todos os detalhes dos cálculos. De qualquer forma, para um subconjunto de configurações, em que a solução (círculo azul) é tangente a dois círculos vermelhos, o seguinte deve funcionar:
1) seja R o raio do círculo azul
2) faça um loop sobre todos os pares de círculos vermelhos, sim Eu sei que isso é O (n2).
3) para cada par de círculos i, j com centros em (xi, yi) e (xj, yj) com o raio respectivo ri e rj, calcule o quadrado da distância entre o par de círculos

d_ij^2=(xi-xj)^2+(yi-yj)^2  

4) coloque todos os pares de círculos que

dij^2<R^2

em uma lista.

5) percorra a lista, encontrando as 2 soluções dos círculos do raio R tangentes aos círculos iej. Para fazer isso, use estas equações junto com esta imagem dois círculos azuis canditates por um par de círculos vermelhos

a = R+ri  
b = R+rj  
c = dij  
α = arccos((b^2+c^2-a^2)/(2bc)  

com as informações acima, você pode encontrar (X1ij, Y1ij) e (X2ij, Y2ij) os centros dos 2 círculos tangentes aos círculos iej. Para cada candidato, o círculo azul passa por todos os outros círculos vermelhos e verifique se não se sobrepõem. Caso contrário, verifique a distância do círculo branco. Se você mantiver a distância menor, acho que terá a solução ao terminar de percorrer a lista de pares de círculos. O algoritmo parece O (n3).


não funciona quando há apenas um círculo
Ewan

ou dois círculos, mas com um ponto de destino fora de ambos
Ewan

o problema é que você não pode ter certeza que você tem todas as casos extremos
Ewan

Além disso. existem soluções únicas para os casos
Ewan

Você precisa anotar todas as suposições sob as quais a solução está correta ou, pelo menos, apontar todos os casos de borda. Alguns deles podem ser óbvios, mas outros não. Por exemplo, isso não funcionará se for possível desenhar uma linha que separa o ponto branco de todos os círculos vermelhos e o ponto branco estiver a menos de R do círculo mais próximo.
Vlad

2

O posicionamento mais próximo ao ponto estará no ponto ou tocando em um círculo.

portanto, verifique primeiro o ponto, depois role o novo círculo em torno da borda de cada círculo existente, calculando a distância do ponto e se você se sobrepuser à medida que avança e mantendo o controle do ponto de distância mínimo. Pare quando você percorrer todos os círculos.

ie verifique todos os pontos nas linhas verdes, além do círculo branco. onde a linha verde é um círculo com raio do vermelho mais o azul

possíveis pontos centrais

você precisa verificar toda a linha verde, não apenas as interseções para cobrir esses casos de arestas.

casos de círculo único

Obviamente, o tamanho da etapa da sua travessia será importante em termos de desempenho. Mas como você declara que o desempenho não é um problema, escolha o valor correspondente à resolução do seu valor de saída. ou seja, flutuar, longo?

esclarecimento:

minha sugestão é a força bruta de todos os pontos ao redor de cada círculo, testando a sobreposição com todos os outros círculos em cada ponto. sem esperteza.

Se a foto de exemplo é indicativa do número de círculos e da resolução, não deve ser um problema para um PC padrão

temos 20 círculos de raio médio 200, ou seja, aproximadamente 20 * 2 π * 200 pontos * 20 testes de interseção = 4800000 iterações

Nota:

Abordagens iterativas como essa são falhas, pois o tamanho da sua etapa, neste caso a resolução da sua saída, pode afetar muito o resultado.

Digamos que eu tenha dois círculos vermelhos separados por 2 pixels e um círculo azul de raio de 1 pixel para espremer entre eles. Claramente, com um dos dois pixels como centro do círculo azul, ele se sobrepõe a um dos vermelhos. mas obviamente há espaço para o círculo se o centro estiver entre os dois pixels.

Daí o meu comentário perguntando sobre a resolução da saída. que você disse que poderia ser qualquer coisa.

você também pode resolver a equação simultânea para cada par de círculos com raio aumentado pelo raio do círculo azul.

isso fornecerá os pontos em que o círculo azul tocará nos dois círculos vermelhos com mais precisão do que na iteração.

Contudo. existem várias condições em que, se você fizer isso, obtém a resposta errada ou não. ie

1 ou nenhum círculo

2 ou mais círculos, mas com o ponto alvo distante e fora deles.

muitos círculos, mas com o ponto alvo próximo à superfície


2
O fato de ele precisar rolar a borda do círculo azul ao redor dos outros círculos é a parte mais fácil de entender. A parte difícil é descobrir as equações / cálculos para fazer isso.
Robert Harvey

1
verdade? (x-x1) ^ 2 + (y-y1) ^ 2 = (r + r1) ^ 2
Ewan

2
E então você precisa fazer tudo isso novamente quando tentar o próximo ponto. Eu sei que o OP disse que o desempenho não era uma preocupação, mas precisa ser concluído antes da morte pelo calor do universo.
Robert Harvey

2
A única maneira de saber se você receberá dez upvotes é publicar seu código C # e ver o que acontece.
Robert Harvey

2
o que eu acho que vai acontecer é o OP irá codificar isso como sua resposta a lição de casa e nunca iremos ouvir falar dele
Ewan

1

Esse plunk contém código de trabalho,

Conceito

Os círculos dados são C1, C2 .... Cn

e coordenadas do círculo Cn é Cnx, Cny e raio é Cr

e o raio do círculo requerido é R

se o círculo azul estiver no local X, Y e se não entrar em conflito com outros círculos, as equações a seguir serão verdadeiras

(C1x - X)^2 + (C1y - Y)^2 > (C1r + R)^2
(C2x - X)^2 + (C2y - Y)^2 > (C2r + R)^2
....
(Cnx - X)^2 + (Cny - Y)^2 > (Cnr + R)^2

mudando a primeira equação,

C1x^2 - 2C1x*X + X^2 + C1y^2 - 2C1y*Y + Y^2 > C1r^2 + 2C1r*R + R^2
X^2 + Y^2 - 2C1x*X - 2C1y*Y > C1r^2 + 2C1r*R + R^2 - C1x^2 - C1y^2

para que as equações possam reescrever como,

X^2 + Y^2 - 2C1x*X - 2C1y*Y > C1r^2 + 2C1r*R + R^2 - C1x^2 - C1y^2
X^2 + Y^2 - 2C2x*X - 2C2y*Y > C2r^2 + 2C2r*R + R^2 - C2x^2 - C2y^2
....
X^2 + Y^2 - 2Cnx*X - 2Cny*Y > Cnr^2 + 2Cnr*R + R^2 - Cnx^2 - Cny^2

Implementação

comece pela coordenada do ponto branco (Xw, Yw),

    var isValidLocation = function(x,y,r){
       var valid = true;
       for (var i = 0; i< circles.length; i++){
          var circle = circles[i];
          valid = valid && ((x*x + y*y - 2*circle.x*x - 2*circle.y*y) > (circle.radius*circle.radius + 2*circle.radius*r + r*r - circle.x*circle.x - circle.y*circle.y));
       }
       return valid;
      };

      var find = function(Xw,Yw,Rw){
        var radius = 0;
        while(true){
          for (var x=-1 * radius ;x <= radius; x++) {
            for (var y=-1 * radius;y <= radius; y++) {
               if (isValidLocation(Xw + x,Yw + y, Rw)){
                 drawCircle(Xw + x,Yw + y,Rw,"#0000FF");
                 return;
               }
            }   
          } 
          radius++;
        }
     }; 

a primeira coordenada encontrada para satisfazer todas as equações é a localização do círculo azul


Alguém pode explicar o que há de errado com essa abordagem?
Pelicano de vôo baixo

Isso é difícil de ler. Use alguns bons nomes e abstrações. Mataria você adicionar um diagrama?
candied_orange

Tanto quanto posso ver, essa abordagem tenta encontrar apenas canais válidos para o círculo azul, mas não o local mais próximo possível. Isso pode ser corrigido, no entanto, a abordagem também faz a suposição (provavelmente inválida) de que há apenas um número finito de coordenadas de valores inteiros.
Doc Brown

Começa pela coordenada do ponto branco e contorna a grade de pesquisa. Por isso, ele não enfrentará nenhuma situação em que tenha um número infinito de coordenadas. Eventualmente, encontrará coordenadas correspondentes.
Pelicano de vôo baixo

1
... para obter uma solução correta em coordenadas inteiras, é necessário usar um raio crescente e tornar seu espaço de pesquisa um círculo desse raio em torno do ponto branco. E embora o OP tenha escrito que a eficiência não é uma preocupação dele, seria uma boa idéia não testar todos os pares de coordenadas já testados em cada loop repetidas vezes.
Doc Brown

0
  • O sendo o ponto que você está tentando estar perto
  • P sendo o ponto que você está procurando (o centro do círculo azul
  • r sendo o raio do círculo azul
  • C0 .. Cn sendo o centro de todos os círculos que restringem a colocação do azul na
  • círculo estendido é um dos círculos com raio estendido por r

    Há algum trabalho extra se O não estiver no centro do círculo. Então, no momento, assuma O == C0

Calcule todas as interseções de todos os círculos com C0, usando seus respectivos raios mais r , ou seja, intercepte os círculos estendidos com o C0 estendido. Se não houver interseções, o ponto que você procura estará em C0, se houver interseções, para cada interseção, verifique se está dentro de outro círculo estendido (você pode limitar-se aos círculos que tiveram interseções com C0). Pegue a primeira interseção que não está em outro círculo estendido como P, pode haver outras.

Se não houver interseções entre os círculos estendidos e C0 que não estão dentro de outro círculo estendido, calcule as interseções de todos os círculos estendidos entre si. Em seguida, verifique essas interseções na ordem da distância para O, novamente se alguma das interseções se encontra dentro de outro círculo estendido, se sim, descarte, se não, esse é o seu resultado.

Se você imaginar isso, desenhe uma linha ao redor de todos os círculos que indicam uma possível localização para o seu círculo azul, a união de todos os círculos estendidos indicará a área que seu círculo azul não pode estar. O ponto que você está procurando é o ponto mais próximo que não está nessa união. Se houver algum ponto em C0 que não esteja nessa união que é a solução, se C0 estiver totalmente coberto, P deverá estar em uma interseção entre dois outros círculos estendidos e deve estar em uma área não coberta por esta união (ou seja, não em um círculo estendido ).

Este é O (n ^ 2), existem algumas maneiras de melhorar isso, porém, uma grade pode ser usada para reduzir o esforço da pesquisa em pares, também acho que classificar os círculos pela proximidade com O (a distância entre o dois círculos reduzidos pelo rádio) ajudariam a limitar o espaço de pesquisa para a pesquisa de cobertura e interseção


0

Possíveis soluções lookup

  1. Verifique se o ponto branco é a solução por si só. Ele cobre maiúsculas e minúsculas com 0 círculos vermelhos e maiúsculas e minúsculas quando os círculos vermelhos estão longe do ponto branco.
  2. Um círculo vermelho
    1. O ponto branco é o centro do círculo. As soluções possíveis são um número infinito de pontos no círculo, com o centro no ponto branco e no raio sendo a soma do raio dos círculos azuis e do diâmetro do círculo vermelho. Vamos chamá-lo de círculo verde .
    2. O ponto branco está em outro lugar. Só existe uma solução possível na linha que conecta o ponto branco e o centro do círculo vermelho, que é o raio do círculo azul longe do ponto em que o círculo vermelho cruza a linha em direção ao ponto branco.
  3. Dois ou mais círculos vermelhos.
    1. Vamos pegar círculos vermelhos, um por um, e procurar a solução possível para cada um deles individualmente, de acordo com o ponto 2 (um círculo).
    2. Para cada par de círculos vermelhos, vamos verificar se você pode desenhar o círculo azul tocando os dois vermelhos. Ou seja, se a distância entre seus centros for igual ou menor que a soma de seus raios mais o diâmetro do círculo azul. Se puder, você tem duas (ou uma, se os círculos vermelhos estão a exatamente um diâmetro de círculo azul) soluções possíveis .

Pesquisa real da solução entre as possíveis soluções

Agora você tem um conjunto de pontos que são possíveis soluções , percorra-os e verifique cada um.

  1. Se o ponto é realmente uma solução. Nenhum círculo vermelho deve ter o centro mais próximo do que o raio até este ponto.
  2. Se estiver mais próximo do ponto branco do que a solução encontrada anteriormente.
  3. Se você tem o círculo verde (ponto 2.1)
    • Se entre pontos individuais não houver solução que pertença ao círculo verde, então o círculo verde é a resposta.
    • Se você tem soluções individuais no círculo verde e precisa de qualquer solução, basta escolher uma delas.
    • Se você possui soluções individuais no círculo verde e precisa de todo o número ilimitado de soluções, precisará resolver outro problema. Você precisa cortar do círculo verde todos os arcos definidos pelo par de soluções individuais de cada círculo vermelho.

NB: Não estou dizendo que a implementação do algoritmo deva ser exatamente descrita. Você pode tentar melhorar o desempenho usando programação dinâmica ou ignorando possíveis soluções, onde é óbvio que elas não funcionarão.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.