Calcolo dell'intersezione di due cerchi?


29

Sto cercando di capire come derivare matematicamente i punti comuni di due cerchi che si intersecano sulla superficie terrestre, dato un centro Lat / Lon e un raggio per ciascun punto.

Ad esempio, dato:

  • Lat / Lon (37.673442, -90.234036) Raggio 107,5 NM
  • Lat / Lon (36.109997, -90.953669) Raggio 145 NM

Dovrei trovare due punti di intersezione con uno di essi (36.948, -088.158).

Sarebbe banalmente facile risolverlo su un piano piano ma non ho alcuna esperienza nel risolvere equazioni su una sfera imperfetta come la superficie terrestre.


1
Se tutti i tuoi raggi saranno così piccoli (meno di diversi chilometri), allora la terra è essenzialmente piatta su questa scala e potresti anche scegliere una proiezione semplice e accurata ed eseguire i soliti calcoli euclidei. Assicurati di calcolare l'intersezione con più di tre cifre decimali: l' imprecisione nella terza cifra decimale è grande quanto uno dei tuoi raggi!
whuber

1
Avrei dovuto aggiungere unità, quei raggi sono in NM, quindi è ancora una piccola distanza rispetto alla superficie terrestre ma più grande di qualche km. In che modo questa scala influenza la distorsione? Sto cercando di trovare una soluzione accurata a meno di <1nm, quindi non deve essere super precisa. Grazie!
Will

Tutto questo è bene sapere, perché dimostra che puoi usare un modello sferico della terra: i modelli ellissoidali più complicati non sono necessari.
whuber

@whuber Questo implica che il problema potrebbe essere ribadito come: trova l'intersezione di 3 sfere in cui una delle sfere è la terra e le altre due sono centrate sui punti con i rispettivi raggi?
Kirk Kuykendall,

@Kirk Sì, questo è il modo di farlo, assumendo un modello sferico della superficie terrestre. Dopo alcuni calcoli preliminari che riducono questo a un caso speciale del problema della trilaterazione in 3D. (I calcoli sono necessari per convertire la distanza lungo gli archi sferici in distanze lungo gli accordi sferici, che diventano i raggi delle due sfere più piccole.)
whuber

Risposte:


21

Non è molto più difficile sulla sfera che sul piano, una volta che lo riconosci

  1. I punti in questione sono le intersezioni reciproche di tre sfere: una sfera centrata sotto la posizione x1 (sulla superficie terrestre) di un dato raggio, una sfera centrata sotto la posizione x2 (sulla superficie terrestre) di un dato raggio e la terra stessa , che è una sfera centrata su O = (0,0,0) di un dato raggio.

  2. L'intersezione di ciascuna delle prime due sfere con la superficie terrestre è un cerchio, che definisce due piani. Le intersezioni reciproche di tutte e tre le sfere si trovano quindi sull'intersezione di quei due piani: una linea .

Di conseguenza, il problema si riduce all'intersezione di una linea con una sfera, il che è semplice.


Ecco i dettagli Gli input sono i punti P1 = (lat1, lon1) e P2 = (lat2, lon2) sulla superficie terrestre, considerati come una sfera, e due raggi corrispondenti r1 e r2.

  1. Converti coordinate geocentriche (lat, lon) in (x, y, z). Come al solito, poiché possiamo scegliere unità di misura in cui la terra ha un raggio unitario,

    x = cos(lon) cos(lat)
    y = sin(lon) cos(lat)
    z = sin(lat).
    

    Nell'esempio, P1 = (-90.234036 gradi, 37.673442 gradi) ha coordinate geocentriche x1 = (-0.00323306, -0.7915, 0.61116) e P2 = (-90.953669 gradi, 36.109997 gradi) ha coordinate geocentriche x2 = (-0.0134464, -0.807775 , 0,589337).

  2. Converti i raggi r1 e r2 (che sono misurati lungo la sfera) in angoli lungo la sfera. Per definizione, un miglio nautico (NM) è 1/60 gradi di arco (che è pi / 180 * 1/60 = 0.0002908888 radianti). Pertanto, come angoli,

    r1 = 107.5 / 60 Degree = 0.0312705 radian
    r2 = 145 / 60 Degree = 0.0421788 radian
    
  3. Il cerchio geodetico del raggio r1 attorno a x1 è l'intersezione della superficie terrestre con una sfera euclidea di raggio sin (r1) centrata su cos (r1) * x1.

  4. Il piano determinato dall'intersezione della sfera del raggio sin (r1) attorno a cos (r1) * x1 e la superficie terrestre è perpendicolare a x1 e passa attraverso il punto cos (r1) x1, da cui la sua equazione è x.x1 = cos (r1) (il "." rappresenta il solito prodotto punto ); allo stesso modo per l'altro piano. Ci sarà un unico punto x0 sull'intersezione di quei due piani che è una combinazione lineare di x1 e x2. Scrivendo x0 = a x1 + b * x2 sono le due equazioni planari

    cos(r1) = x.x1 = (a*x1 + b*x2).x1 = a + b*(x2.x1)
    cos(r2) = x.x2 = (a*x1 + b*x2).x2 = a*(x1.x2) + b
    

    Utilizzando il fatto che x2.x1 = x1.x2, che scriverò come q, la soluzione (se esiste) è data da

    a = (cos(r1) - cos(r2)*q) / (1 - q^2),
    b = (cos(r2) - cos(r1)*q) / (1 - q^2).
    

    Nell'esempio corrente, computo a = 0.973503 eb = 0.0260194.

    Evidentemente abbiamo bisogno di q ^ 2! = 1. Ciò significa che x1 e x2 non possono essere né lo stesso punto né punti antipodali.

  5. Ora tutti gli altri punti sulla linea di intersezione dei due piani differiscono da x0 per alcuni multipli di un vettore n che è reciprocamente perpendicolare a entrambi i piani. Il prodotto incrociato

    n = x1~Cross~x2
    

    fa il lavoro fornito n è diverso da zero: ancora una volta, ciò significa che x1 e x2 non sono né coincidenti né diametralmente opposti. (Dobbiamo fare attenzione a calcolare il prodotto incrociato con alta precisione, perché comporta sottrazioni con molta cancellazione quando x1 e x2 sono vicini tra loro.) Nell'esempio, n = (0,0272194, -0,00631254, -0,00803124) .

  6. Pertanto, cerchiamo fino a due punti della forma x0 + t * n che giacciono sulla superficie terrestre: cioè la loro lunghezza è uguale a 1. Equivalentemente, la loro lunghezza al quadrato è 1:

    1 = squared length = (x0 + t*n).(x0 + t*n) = x0.x0 + 2t*x0.n + t^2*n.n = x0.x0 + t^2*n.n
    

    Il termine con x0.n scompare perché x0 (essendo una combinazione lineare di x1 e x2) è perpendicolare a n. Le due soluzioni sono facilmente

    t = sqrt((1 - x0.x0)/n.n)
    

    e il suo negativo. Ancora una volta è richiesta un'alta precisione, perché quando x1 e x2 sono vicini, x0.x0 è molto vicino a 1, con conseguente perdita di precisione in virgola mobile. Nell'esempio, t = 1.07509 oppure t = -1.07509. I due punti di intersezione sono quindi uguali

    x0 + t*n = (0.0257661, -0.798332, 0.601666)
    x0 - t*n = (-0.0327606, -0.784759, 0.618935)
    
  7. Infine, possiamo convertire queste soluzioni in (lat, lon) convertendo geocentrico (x, y, z) in coordinate geografiche:

    lon = ArcTan(x,y)
    lat = ArcTan(Sqrt[x^2+y^2], z)
    

    Per la longitudine, utilizzare i valori di ritorno arctangent generalizzati nell'intervallo da -180 a 180 gradi (nelle applicazioni di elaborazione, questa funzione accetta sia x che y come argomenti anziché solo il rapporto y / x; a volte viene chiamato "ATan2").

    Ottengo le due soluzioni (-88.151426, 36.989311) e (-92.390485, 38.238380), mostrate nella figura come punti gialli.

Figura 3D

Gli assi visualizzano le coordinate geocentriche (x, y, z). La macchia grigia è la porzione della superficie terrestre da -95 a -87 gradi di longitudine, da 33 a 40 gradi di latitudine (segnata con un reticolo di un grado). La superficie terrestre è stata resa parzialmente trasparente per mostrare tutte e tre le sfere. La correttezza delle soluzioni calcolate è evidente da come i punti gialli si trovano alle intersezioni delle sfere.


Bill, è fantastico. Un chiarimento che potresti aggiungere, basato su qualcuno che stava cercando di implementarlo. Nel passaggio 2 non dai esplicitamente la conversione da gradi a radianti.
Jersey Andy,

@Jersey Grazie per la modifica suggerita. L'ho cambiato un po 'per evitare la ridondanza e per mantenere le formule il più chiare possibile. Dopo aver letto il thread a cui ti riferisci, ho anche inserito un link per spiegare il punto prodotto.
whuber

8

Il caso ellissoidale :

Questo problema è una generalizzazione di quello di trovare confini marittimi definiti come "linee mediane" e c'è una vasta letteratura su questo argomento. La mia soluzione a questo problema è sfruttare la proiezione azimutale equidistante:

  1. Indovina nel punto di intersezione
  2. Proiettare i due punti base usando questo indovinato punto di intersezione come il centro di una equidistante proiezione azimutale,
  3. Risolvi il problema dell'intersezione nello spazio proiettato 2d.
  4. Se il nuovo punto di intersezione è troppo lontano da quello vecchio, tornare al passaggio 2.

Questo algoritmo converge in modo quadratico e fornisce una soluzione accurata su un ellissoide. (La precisione è richiesta nel caso dei confini marittimi, poiché determina i diritti di pesca, petrolio e minerali.)

Le formule sono riportate nella Sezione 14 di Geodetica su un ellissoide di rivoluzione . La proiezione azimutale equidistante ellissoidale è fornita da GeographicLib . Una versione MATLAB è disponibile presso le proiezioni geodetiche per un ellissoide .


+1 Questo è un documento straordinario: la tua modesta descrizione qui non rende giustizia.
whuber

Vedi anche il mio documento più breve sulla geodetica "Algorithms for geodesics" dx.doi.org/10.1007/s00190-012-0578-z (download gratuito!) Più errata e addenda per questi articoli geographiclib.sf.net/geod-addenda.html
Cffk,

1

Ecco un codice R per fare questo:

p1 <- cbind(-90.234036, 37.673442) 
p2 <- cbind(-90.953669, 36.109997 )

library(geosphere)
steps <- seq(0, 360, 0.1)
c1 <- destPoint(p1, steps, 107.5 * 1852)
c2 <- destPoint(p2, steps, 145 * 1852)

library(raster)
s1 <- spLines(c1)
s2 <- spLines(c2)

i <- intersect(s1, s2)
coordinates(i)

#        x        y
# -92.38241 38.24267
# -88.15830 36.98740

s <- bind(s1, s2)
crs(s) <- "+proj=longlat +datum=WGS84"
plot(s)
points(i, col='red', pch=20, cex=2)

1

A seguito della risposta di @ whuber , ecco un po 'di codice Java che è utile per due motivi:

  • evidenzia un gotcha riguardante ArcTan (per Java e forse altre lingue?)
  • gestisce i possibili casi limite, incluso uno non menzionato nella risposta di @ whuber.

Non è ottimizzato o completo (ho escluso classi ovvie come Point), ma dovrebbe fare il trucco.

public static List<Point> intersection(EarthSurfaceCircle c1, EarthSurfaceCircle c2) {

    List<Point> intersections = new ArrayList<Point>();

    // project to (x,y,z) with unit radius
    UnitVector x1 = UnitVector.toPlanar(c1.lat, c1.lon);
    UnitVector x2 = UnitVector.toPlanar(c2.lat, c2.lon);

    // convert radii to radians:
    double r1 = c1.radius / RadiusEarth;
    double r2 = c2.radius / RadiusEarth;

    // compute the unique point x0
    double q = UnitVector.dot(x1, x2);
    double q2 = q * q;
    if (q2 == 1) {
        // no solution: circle centers are either the same or antipodal
        return intersections;
    }
    double a = (Math.cos(r1) - q * Math.cos(r2)) / (1 - q2);
    double b = (Math.cos(r2) - q * Math.cos(r1)) / (1 - q2);
    UnitVector x0 = UnitVector.add(UnitVector.scale(x1, a), UnitVector.scale(x2, b));

    // we only have a solution if x0 is within the sphere - if not,
    // the circles are not touching.
    double x02 = UnitVector.dot(x0, x0);
    if (x02 > 1) {
        // no solution: circles not touching
        return intersections;
    }

    // get the normal vector:
    UnitVector n = UnitVector.cross(x1, x2);
    double n2 = UnitVector.dot(n, n);
    if (n2 == 0) {
        // no solution: circle centers are either the same or antipodal
        return intersections;
    }

    // find intersections:
    double t = Math.sqrt((1 - UnitVector.dot(x0, x0)) / n2);
    intersections.add(UnitVector.toPolar(UnitVector.add(x0, UnitVector.scale(n, t))));
    if (t > 0) {
        // there's only multiple solutions if t > 0
        intersections.add(UnitVector.toPolar(UnitVector.add(x0, UnitVector.scale(n, -t))));
    }
    return intersections;
}

Inoltre, è importante notare l'uso di atan2- è il contrario di quello che ti aspetteresti dalla risposta di @ whuber (non so perché, ma funziona):

    public static Point toPolar(UnitVector a) {
        return new Point(
                Math.toDegrees(Math.atan2(a.z, Math.sqrt(a.x * a.x + a.y * a.y))),
                Math.toDegrees(Math.atan2(a.y, a.x)));          
    }

0

Codice "R" funzionante per la risposta @wuhber.

P1 <- c(37.673442, -90.234036)
P2 <- c(36.109997, -90.953669) 

#1 NM nautical-mile is 1852 meters
R1 <- 107.5
R2 <- 145

x1 <- c(
  cos(deg2rad(P1[2])) * cos(deg2rad(P1[1])),  
  sin(deg2rad(P1[2])) * cos(deg2rad(P1[1])),
  sin(deg2rad(P1[1]))
);

x2 <- c(
  cos(deg2rad(P2[2])) * cos(deg2rad(P2[1])),
  sin(deg2rad(P2[2])) * cos(deg2rad(P2[1])),
  sin(deg2rad(P2[1]))
);

r1 = R1 * (pi/180) * (1/60)
r2 = R2 * (pi/180) * (1/60)

q = dot(x1,x2)
a = (cos(r1) - cos(r2) * q) / (1 - q^2)
b = (cos(r2) - cos(r1) * q)/ (1 - q^2)

n <- cross(x1,x2)

x0 = a*x1 + b*x2


t = sqrt((1 - dot(x0, x0))/dot(n,n))

point1 = x0 + (t * n)
point2 = x0 - (t * n)

lat1 = rad2deg(atan2(point1[2] ,point1[1]))
lon1= rad2deg(asin(point1[3]))
paste(lat1, lon1, sep=",")

lat2 = rad2deg(atan2(point2[2] ,point2[1]))
lon2 = rad2deg(asin(point2[3]))
paste(lat2, lon2, sep=",")

-1

Se uno dei cerchi è il Nortstar, allora c'è un modo più semplice con la sfera unitaria.

Puoi misurare la tua latitudine con Nortstar. Quindi hai una posizione relativa su questa sfera. v1 (0, sin (la), cos (la)) Conosci la posizione (angolo) di un'altra stella (stella2), da almanacco. v2 (sin (lo2) * cos (la2), sin (la2), cos (lo2) * cos (la2)) I suoi vettori. Dall'equazione della sfera.

lo2 è la longitudine relativa. È sconosciuto .

L'angolo tra te e la stella2, puoi anche misurare, (m) E sai, il prodotto interno del vettore di due unità è cos (angolo) di mezzo. cos (m) = punto (v1, v2) ora puoi calcolare la longitudine relativa (lo2). LO2 = acos ((cos (m) -sin (la) * sin (LA2)) / (cos (la) * cos (LA2)))

Dopo tutto aggiungi la vera longitudine di star2 a lo2. (o sub, dipende dal suo lato ovest da te, o est.) lo2 ora è la tua longitudine.

Scusate il mio inglese, non imparo mai questa lingua.


2 cose: Northstar significa stella polare.

Un altro. Poiché l'angolo misurato relativamente in orizzontale, necessita sempre di una correzione di 90 angoli. È valido anche per l'angolo m.

ps: media angolo reale: posizione della stella - correzione del tempo.


Non è chiaro come questo risponda alla domanda.
whuber
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.