Trova la soluzione più adatta per il cerchio


12

Di seguito è riportata un'immagine di esempio, se ho un punto del punto bianco nel mezzo e voglio trovare la posizione più vicina possibile per il cerchio blu (che è ovviamente nella posizione in cui l'ho posizionato) se tutti i cerchi rossi esistono già . Come posso trovare quella posizione?

Le prestazioni per me non sono una delle maggiori preoccupazioni per questa applicazione.

inserisci qui la descrizione dell'immagine


1
qual è il significato del cerchio nero? puoi posizionare il cerchio blu su di esso?
Ewan,

2
Quindi, per essere chiari, vuoi la posizione in cui puoi posizionare il cerchio blu in modo tale che sia la distanza più breve possibile dal punto bianco senza sovrapporre nessuno degli altri cerchi?
Robert Harvey,


2
Tutti i cerchi toccheranno sempre qualche altro cerchio in almeno un posto?
Robert Harvey,

Risposte:


4

Questa non è una soluzione generale, poiché ci sono diverse situazioni in cui non fornirà la posizione del cerchio blu con la distanza più breve dal punto bianco. Ad esempio, se hai 100 palline rosse raggruppate insieme e il punto bianco è lontano da questo gruppo di palline rosse, nessuna delle palline rosse avrà alcuna influenza nella posizione del cerchio blu che può essere semplicemente centrata sul punto bianco . Né mostrerà tutti i dettagli dei calcoli. Ad ogni modo, per un sottoinsieme di configurazioni, in cui la soluzione (cerchio blu) è tangente a due cerchi rossi, dovrebbe funzionare come segue:
1) lasciare che R sia il raggio del cerchio blu
2) fare un ciclo su tutta la coppia di cerchi rossi, sì So che questo è O (n2).
3) per ogni coppia di cerchi i, j con i centri in (xi, yi) e (xj, yj) con il rispettivo raggio ri e rj, calcola il quadrato della distanza tra la coppia di cerchi

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

4) metti tutte le coppie di cerchi

dij^2<R^2

in un elenco.

5) attraversare l'elenco, trovando le 2 soluzioni dei cerchi di raggio R tangenti a entrambi i cerchi i e j. Per fare questo usa queste equazioni insieme a questa immagine due canditi cerchio blu per una coppia di cerchi rossi

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

con le informazioni di cui sopra puoi trovare (X1ij, Y1ij) e (X2ij, Y2ij) i centri dei 2 cerchi tangenti ai cerchi i e j. Per ogni candidato cerchio blu loop su tutti gli altri cerchi rossi e vedere se non si sovrappongono. Se lo scartano, altrimenti controlla la distanza dal cerchio bianco. Se mantieni quello con una distanza minore, penso che avrai la soluzione quando finisci di attraversare l'elenco delle coppie di cerchi. L'algoritmo sembra O (n3).


non funziona quando esiste un solo cerchio
Ewan,

o due cerchi, ma con un punto target al di fuori di entrambi
Ewan,

il problema è che non puoi essere sicuro di avere tutti i casi limite
Ewan

anche. ci sono soluzioni uniche per questi casi
Ewan,

È necessario annotare tutte le ipotesi in base alle quali la soluzione è corretta o almeno indicare tutti i casi limite. Alcuni di loro possono essere ovvi, ma altri no. Ad esempio, ciò non funzionerà se è possibile disegnare una linea che separa il punto bianco da tutti i cerchi rossi e il punto bianco si trova a meno di R dal cerchio più vicino.
Vlad

2

La posizione più vicina al punto sarà sul punto o toccherà un cerchio.

pertanto, prima controlla il punto, quindi ruota il nuovo cerchio attorno al bordo di ciascun cerchio esistente, calcolando la distanza dal punto e se ti sovrapponi mentre procedi e tenendo traccia del punto di distanza minima. Fermati quando hai attraversato ogni cerchio.

vale a dire. controlla tutti i punti sulle linee verdi, oltre al cerchio bianco. dove la linea verde è un cerchio con raggio del rosso più il blu

possibili punti centrali

devi controllare l'intera linea verde, non solo le intersezioni in modo da coprire questi casi limite.

casi a cerchio singolo

Ovviamente la dimensione del passo della traversata sarà importante in termini di prestazioni. Ma poiché affermi che le prestazioni non sono un problema, scegli il valore corrispondente alla risoluzione del valore di output. cioè galleggiante, lungo?

una precisazione:

il mio suggerimento è quello di forzare la forza di tutti i punti attorno a ciascun cerchio per verificarne la sovrapposizione con tutti gli altri cerchi in ciascun punto. nessuna intelligenza.

Se l'immagine di esempio è indicativa del numero di cerchi e della risoluzione, non dovrebbe essere un problema per un PC standard

abbiamo 20 cerchi di raggio medio 200, quindi circa 20 * 2 π * 200 punti * 20 test di intersezione = 4800000 iterazioni

Nota:

Approcci iterativi come questo sono imperfetti in quanto la dimensione del passo, in questo caso la risoluzione dell'output, può influire notevolmente sul risultato.

Supponi di avere due cerchi rossi a 2 pixel di distanza e un cerchio blu di 1 pixel di raggio per schiacciarli. Chiaramente con uno dei due pixel come centro del cerchio blu si sovrapporrà uno dei rossi. ma ovviamente c'è spazio per il cerchio se il centro si trova tra i due pixel.

Da qui il mio commento che chiede la risoluzione dell'output. che hai detto potrebbe essere qualsiasi cosa.

puoi anche risolvere l'equazione simultanea per ogni coppia di cerchi con aumento del raggio del raggio del cerchio blu.

questo ti darà i punti in cui il cerchio blu toccherà entrambi i cerchi rossi in modo più accurato rispetto all'iterazione.

Tuttavia. ci sono diverse condizioni in cui se lo fai solo ottieni la risposta sbagliata o nessuna. vale a dire.

1 o nessun cerchio

2 o più cerchi ma con un punto bersaglio molto lontano e al di fuori di essi.

molti cerchi ma con un punto bersaglio vicino alla superficie


2
Che abbia bisogno di rotolare il bordo del cerchio blu attorno all'esterno degli altri cerchi è la parte facile da capire. La parte difficile è capire le equazioni / i calcoli per farlo.
Robert Harvey,

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

2
E poi devi rifare tutto questo quando provi il punto successivo. So che l'OP ha affermato che le prestazioni non erano una preoccupazione, ma devono essere completate prima della morte per calore dell'universo.
Robert Harvey,

2
L'unico modo per sapere se otterrai dieci voti è pubblicare il tuo codice C # e vedere cosa succede.
Robert Harvey,

2
quello che penso accadrà è che l'OP lo codificherà come risposta ai suoi compiti e non lo sentiremo mai più
Ewan

1

Questo plunk contiene codice funzionante,

Concetto

I cerchi indicati sono C1, C2 .... Cn

e coordinate del cerchio Cn è Cnx, Cny e il raggio è Cr

e il raggio del cerchio richiesto è R

se il cerchio blu si trova nella posizione X, Y e se non è in conflitto con altri cerchi, le seguenti equazioni sono vere

(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

cambiando prima equazione,

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

così le equazioni possono riscrivere come,

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

Implementazione

iniziare dalla coordinata del punto bianco (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++;
        }
     }; 

la prima coordinata trovata per soddisfare tutte le equazioni è la posizione del cerchio blu


Qualcuno può spiegare cosa c'è che non va in questo approccio?
Low Flying Pelican

Che è difficile da leggere. Usa alcuni buoni nomi e astrazioni. Ti ucciderebbe per aggiungere un diagramma?
candied_orange,

Per quanto posso vedere, questo approccio cerca di trovare solo posizionamenti validi per il cerchio blu, ma non la posizione più vicina possibile. Ciò potrebbe essere risolto, tuttavia, l'approccio rende anche l'assunto (molto probabilmente non valido) che ci siano solo un numero finito di coordinate di valori interi.
Doc Brown,

Inizia dalla coordinata del punto bianco e lo circonda espandendo la griglia di ricerca. Per questo motivo non affronterà alcuna situazione in cui ha un numero infinito di coordinate .. Alla fine troverà le coordinate corrispondenti.
Low Flying Pelican

1
... per una soluzione corretta in coordinate intere, devi utilizzare un raggio crescente e rendere il tuo spazio di ricerca un cerchio di questo raggio attorno al punto bianco. E sebbene l'OP abbia scritto che l'efficienza non è la sua preoccupazione, sarebbe comunque una buona idea non testare ripetutamente ogni coppia di coordinate già testata in ogni loop.
Doc Brown,

0
  • O essendo il punto a cui stai cercando di essere vicino
  • P è il punto che stai cercando (il centro del cerchio blu
  • r è il raggio del cerchio blu
  • C0 .. Cn essendo i centri di tutti i cerchi che limitano il posizionamento del blu acceso
  • cerchio esteso è uno dei cerchi con raggio esteso di r

    C'è del lavoro extra se O non è al centro di un cerchio. Quindi adesso supponiamo O == C0

Calcola tutte le intersezioni di tutti i cerchi con C0, usando i rispettivi raggi più la r , cioè intersecano i cerchi estesi con C0 esteso. Se non ci sono intersezioni, il punto che stai cercando è ovunque su C0, se ci sono intersezioni, per ogni intersezione controlla se si trova all'interno di un altro cerchio esteso (puoi limitarti ai cerchi che avevano intersezioni con C0). Prendi la prima intersezione che non si trova in un altro cerchio esteso come P, potrebbero essercene altri.

Se non ci sono intersezioni tra i cerchi estesi e C0 che non si trovano all'interno di un altro cerchio esteso, calcola le intersezioni di tutti i cerchi estesi tra loro. Quindi controlla queste intersezioni in ordine di distanza da O, anche se una qualsiasi delle intersezioni si trova all'interno di un altro cerchio esteso, se sì scartare, se no questo è il tuo risultato.

Se immagini questo immaginando di tracciare una linea attorno a tutti i cerchi che indicano una possibile posizione per il tuo cerchio blu, prendere l'unione di tutti i cerchi estesi indicherà l'area che il tuo cerchio blu non può essere. Il punto che stai cercando è il punto più vicino che non è in quell'unione. Se c'è qualche punto su C0 che non è in quell'unione che è la soluzione, se C0 è completamente coperto, allora P deve trovarsi su un'intersezione tra altri due cerchi estesi e deve trovarsi in un'area che non è coperta da questa unione (cioè non in un cerchio esteso ).

Questo è O (n ^ 2), ci sono alcuni modi per migliorare questo, tuttavia una griglia può essere utilizzata per ridurre lo sforzo della ricerca saggia della coppia, anche io penso di ordinare i cerchi in base alla loro vicinanza a O, (la distanza tra il due cerchi ridotti dalla radio) aiuterebbero a limitare lo spazio di ricerca per la copertura e la ricerca degli incroci


0

Possibili soluzioni LookUp

  1. Controlla se il punto bianco è la soluzione da solo. Copre il caso con 0 cerchi rossi e il caso banale quando i cerchi rossi sono lontani dal punto bianco.
  2. Un cerchio rosso
    1. Il punto bianco è il centro del cerchio. Le possibili soluzioni sono il numero infinito di punti sul cerchio con il suo centro nel punto bianco e il raggio è la somma del raggio dei cerchi blu e del diametro del cerchio rosso. Chiamiamolo il cerchio verde .
    2. Il punto bianco è altrove. C'è solo una possibile soluzione sulla linea che collega il punto bianco e il centro del cerchio rosso, è il raggio del cerchio blu lontano dal punto in cui il cerchio rosso attraversa la linea verso il punto bianco.
  3. Due o più cerchi rossi.
    1. Prendiamo i cerchi rossi uno per uno e cerchiamo la possibile soluzione per ciascuno di essi individualmente secondo il punto 2 (un cerchio).
    2. Per ogni coppia di cerchi rossi controlliamo se puoi disegnare il cerchio blu toccando entrambi quelli rossi. Vale a dire se la distanza tra i loro centri è uguale o inferiore alla somma dei loro raggi più il diametro del cerchio blu. Se puoi, allora hai due (o una se i cerchi rossi sono esattamente a un diametro di cerchio blu di distanza) possibili soluzioni .

Ricerca della soluzione effettiva tra le possibili soluzioni

Ora hai una serie di punti che sono possibili soluzioni , scorrere attraverso di essi e controllare per ciascuno.

  1. Se il punto è in realtà una soluzione. Nessun cerchio rosso dovrebbe avere il suo centro più vicino del suo raggio a questo punto.
  2. Se è più vicino al punto bianco della soluzione trovata prima.
  3. Se hai il cerchio verde (punto 2.1)
    • Se tra i singoli punti non esiste una soluzione che appartiene al cerchio verde, allora il cerchio verde è la risposta.
    • Se hai soluzioni individuali sul cerchio verde e hai bisogno di qualsiasi soluzione, prendine una.
    • Se hai soluzioni individuali sul cerchio verde e hai bisogno di tutto il numero illimitato di soluzioni, devi risolvere un altro problema. È necessario tagliare dal cerchio verde tutti gli archi definiti da una coppia di soluzioni individuali da ciascun cerchio rosso.

NB: Non sto dicendo che l'implementazione dell'algoritmo dovrebbe essere descritta esattamente. Puoi provare a migliorare le prestazioni utilizzando la programmazione dinamica o saltando possibili soluzioni in cui è ovvio che non funzioneranno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.