Обчислення перетину двох кіл?


29

Я намагаюся розібратися, як математично вивести спільні точки двох пересічних кіл на земній поверхні, задавши центр Lat / Lon і радіус для кожної точки.

Наприклад, наведено:

  • Ширина / Дов. (37,673442, -90,234036) Радіус 107,5 Нм
  • Lat / Lon (36.109997, -90.953669) Радіус 145 Нм

Мені слід знайти дві точки перетину, одна з яких є (36.948, -088.158).

Це було б тривіально легко вирішити на плоскій площині, але я не маю досвіду вирішення рівнянь на недосконалій сфері, такій як земна поверхня.


1
Якщо всі ваші радіуси будуть такою маленькою (менше декількох кілометрів), то Земля по суті є плоскою в такому масштабі, і ви також можете вибрати точну, просту проекцію та виконати звичайні евклідові обчислення. Переконайтеся, що ви перераховуєте перетин на більше трьох десяткових знаків - неточність у третьому десятковому знаку така ж велика, як і будь-який із ваших радіусів!
whuber

1
Я мав би додати одиниці, цей радіус знаходиться в NM, тому це ще невелика відстань відносно земної поверхні, але більша, ніж на кілька км. Як ця шкала впливає на спотворення? Я намагаюся знайти рішення з точністю до <1 нм, тому воно не повинно бути надто точним. Спасибі!
Чи буде

Це все добре знати, адже це показує, що ви можете використовувати сферичну модель землі - більш складні еліпсоїдальні моделі зайві.
whuber

@whuber Чи означає це, що проблема може бути перетворена так: знайдіть перетин 3-х сфер, де однією із сфер є земля, а дві інші зосереджені на точках з відповідними радіусами?
Кірк Куйкендалл

@Kirk Так, це зробити так, припускаючи сферичну модель земної поверхні. Після деяких попередніх розрахунків, які зводять це до особливого випадку трилатеральної проблеми в 3D. (Розрахунки потрібні для перетворення відстані вздовж сферичних дуг на відстані вздовж сферичних акордів, які стають радіусами двох менших сфер.)
whuber

Відповіді:


21

На кулі це не набагато складніше, ніж на площині, коли ти це визнаєш

  1. Питання, про які йдеться, - це взаємні перетини трьох сфер: сфери, центрованої під розташуванням x1 (на земній поверхні) заданого радіуса, сфери, центрованої під розташуванням x2 (на земній поверхні) заданого радіуса, і самої землі , яка є сферою, центрованою в O = (0,0,0) заданого радіуса.

  2. Перетин кожної з перших двох сфер із земною поверхнею - це коло, яке визначає дві площини. Тому взаємні перетини всіх трьох сфер лежать на перетині цих двох площин: прямої .

Отже, проблема зводиться до перетину лінії зі сферою, що легко.


Ось деталі. Вхідні дані - точки P1 = (lat1, lon1) і P2 = (lat2, lon2) на земній поверхні, що розглядаються як сфера, і два відповідні радіуси r1 і r2.

  1. Перетворити (лат, lon) в (x, y, z) геоцентричні координати. Як завжди, тому що ми можемо вибрати одиниці вимірювання, у яких Земля має одиничний радіус,

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

    У прикладі P1 = (-90.234036 градусів, 37.673442 градусів) має геоцентричні координати x1 = (-0.00323306, -0.7915, 0.61116), а P2 = (-90.953669 ступінь, 36.109997 градусів) має геоцентричні координати x2 = (-0.0134464, -0.8080) , 0,589337).

  2. Перетворіть радіуси r1 і r2 (які вимірюються вздовж сфери) в кути вздовж сфери. За визначенням, одна морська миля (НМ) - це 1/60 градусного рівня дуги (що становить pi / 180 * 1/60 = 0,0002908888 радіанів). Тому, як кути,

    r1 = 107.5 / 60 Degree = 0.0312705 radian
    r2 = 145 / 60 Degree = 0.0421788 radian
    
  3. Геодезичний коло радіуса r1 навколо x1 є перетином поверхні Землі з евклідової сфери радіуса гріха (r1) з центром в Cos (r1) * x1.

  4. Площина, що визначається перетином сфери радіуса sin (r1) навколо cos (r1) * x1, а земна поверхня перпендикулярна x1 і проходить через точку cos (r1) x1, звідки її рівняння x.x1 = cos (r1) ("." являє собою звичайний крапковий продукт ); аналогічно для іншої площини. На перетині цих двох площин буде унікальна точка x0, що є лінійною комбінацією x1 і x2. Записуючи x0 = a x1 + b * x2 два плоских рівняння

    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
    

    Використовуючи той факт, що x2.x1 = x1.x2, який я запишу як q, рішення (якщо воно існує) задається

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

    У прикладі запуску я обчислюю a = 0,973503 і b = 0,0260194.

    Очевидно, що нам потрібно q ^ 2! = 1. Це означає, що x1 і x2 не можуть бути ні однаковою, ні антиподальною.

  5. Тепер усі інші точки на лінії перетину двох площин відрізняються від x0 деяким кратним вектора n, який взаємно перпендикулярний обом площинам. Хрестовий виріб

    n = x1~Cross~x2
    

    чи задана робота n є ненульовою: ще раз це означає, що x1 і x2 не є ні збігом, ні діаметрально протилежними. (Нам потрібно подбати про обчислення поперечного добутку з високою точністю, оскільки воно включає віднімання з великою кількістю скасування, коли х1 і х2 близькі один до одного.) У прикладі n = (0,0272194, -0,00631254, -0,00803124) .

  6. Тому ми шукаємо до двох точок вигляду x0 + t * n, які лежать на земній поверхні: тобто їх довжина дорівнює 1. Еквівалентно, що їх довжина в квадраті дорівнює 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
    

    Термін з x0.n зникає, оскільки x0 (будучи лінійною комбінацією x1 і x2) перпендикулярно n. Два рішення легко

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

    і його негативний. Ще раз вимагається висока точність, тому що, коли x1 і x2 близькі, x0.x0 дуже близький до 1, що призводить до деякої втрати точності з плаваючою точкою. У прикладі t = 1,07509 або t = -1,07509. Тому дві точки перетину рівні

    x0 + t*n = (0.0257661, -0.798332, 0.601666)
    x0 - t*n = (-0.0327606, -0.784759, 0.618935)
    
  7. Нарешті, ми можемо перетворити ці рішення назад у (lat, lon), перетворивши геоцентричні (x, y, z) в географічні координати:

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

    Для довготи використовуйте узагальнені значення повернення арктангенту в діапазоні від -180 до 180 градусів (при обчислювальних програмах ця функція приймає як аргументи x, так і y, а не просто співвідношення y / x; її іноді називають "ATan2").

    Я отримую два рішення (-88.151426, 36.989311) та (-92.390485, 38.238380), зображені на рисунку у вигляді жовтих крапок.

3D-фігура

На осях відображаються геоцентричні координати (x, y, z). Сірий наліт - це частина земної поверхні від -95 до -87 градусів довготи, широта від 33 до 40 градусів (відмічена в один градус решіткою). Земна поверхня була зроблена частково прозорою для показу всіх трьох сфер. Правильність обчислених рішень очевидна тим, як жовті точки сидять на перетинах сфер.


Білл, це приголомшливо. Одне уточнення, яке ви могли б додати, ґрунтуючись на тому, хто намагався його здійснити. На кроці 2 ви не даєте явного перетворення градусів на радіани.
Джерсі Енді

@Jersey Дякую за запропоновані зміни. Я трохи змінив це, щоб уникнути надмірності та зберегти формули максимально чіткими. Прочитавши нитку, на яку ви посилаєтесь, я також вставив посилання, щоб пояснити крапковий продукт.
whuber

8

Еліпсоїдальної випадок:

Ця проблема є узагальненням пошуку морських кордонів, визначених як "серединні лінії", і є велика література з цієї теми. Моє рішення цієї проблеми полягає в використанні рівновіддаленої азимутальної проекції:

  1. Вгадайте у точці перетину
  2. Проектуйте дві базові точки, використовуючи цю здогадану точку перетину як центр рівновідставної азимутальної проекції,
  3. Розв’яжіть задачу перетину в проектованому просторі 2d.
  4. Якщо нова точка перетину занадто далека від старої, поверніться до кроку 2.

Цей алгоритм сходить квадратично і дає точне рішення на еліпсоїді. (Точність необхідна у випадку морських кордонів, оскільки вона визначає права риболовлі, нафти та корисних копалин.)

Формули наведені у розділі 14 геодезики про еліпсоїд обертання . Еліпсоїдальна рівновідставна азимутальна проекція забезпечується GeographicLib . Версія MATLAB доступна в геодезичних проекціях для еліпсоїда .


+1 Це дивовижний документ: ваш скромний опис тут не робить це справедливим.
whuber

Дивіться також мій коротший документ про геодезику "Алгоритми геодезики" dx.doi.org/10.1007/s00190-012-0578-z (безкоштовно завантажити!) Плюс помилки та доповнення для цих робіт geographiclib.sf.net/geod-addenda.html
cffk

1

Ось декілька код R для цього:

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

Виходячи з відповіді @ whuber , ось код Java, який корисний з двох причин:

  • він підкреслює діточку щодо ArcTan (для Java, а може й інших мов?)
  • він обробляє можливі крайові випадки, включаючи той, який не згадується у відповіді @ whuber.

Це не оптимізоване чи повне (я вийшов із очевидних класів на кшталт Point), але повинен робити свою справу.

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;
}

Також важливо звернути увагу на використання atan2- це зворотній бік того, що ви очікували від відповіді @ whuber (не знаю чому, але це працює):

    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

Робочий код "R" для відповіді @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

Якщо одним з кола є Nortstar, то існує найпростіший спосіб з одиничною сферою.

Ви можете виміряти свою широту за допомогою Nortstar. Тоді у вас є відносна позиція щодо цієї сфери. v1 (0, sin (la), cos (la)) Ви знаєте положення (кут) іншої зірки (star2), з альманаху. v2 (sin (lo2) * cos (la2), sin (la2), cos (lo2) * cos (la2)) Його вектори. З рівняння сфери.

lo2 - відносна довгота. Її невідомо .

Кут між вами та зіркою2 ви також можете виміряти, (м) І знаєте, внутрішнєвиробництво двох одиничних векторів - це cos (кут) між. cos (m) = крапка (v1, v2) u може тепер обчислити відносну довготу (lo2). lo2 = acos ((cos (m) -sin (la) * sin (la2)) / (cos (la) * cos (la2)))

Адже ви додасте справжню довготу зірки2 до lo2. (або суб, залежати від західного боку від вас або сходу.) lo2 тепер ваша довгота.

Вибачте за мою англійську, я ніколи не вивчаю цю мову.


2 речі: Північна зірка середньої полюсної зірки.

Ще одна. Оскільки кут, виміряний до горизонту відносно, завжди потребує корекції на 90 кут. Її також до m кут.

ps: середнє значення кута: положення зірки - корекція часу.


Не очевидно, як це відповідає на питання.
whuber
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.