Скажем, у меня есть произвольный набор пар широты и долготы, представляющих точки на некоторой простой замкнутой кривой. В декартовом пространстве я мог легко вычислить площадь, заключенную такой кривой, используя теорему Грина. Каков аналогичный подход к вычислению площади на поверхности сферы? Я предполагаю, что я за то, что (хотя бы некоторое приближение) алгоритм функция Matlab areaint
.
Расчетная площадь, заключенная в полигон на поверхности Земли
Ответ 1
Есть несколько способов сделать это.
1) Включить вклады от широтных полос. Здесь площадь каждой полосы будет (Rcos (A) (B1-B0)) (RdA), где A - широта, B1 и B0 - начальная и конечная долготы, а все углы находятся в радианах.
2) Разбейте поверхность на сферические треугольники и вычислите площадь с использованием теоремы Жирара и добавьте их вверх.
3) Как предложено здесь Джеймсом Шеком, в работе ГИС они используют проекцию, сохраняющую область, на плоское пространство и вычисляют площадь там.
Из описания ваших данных в звуках, подобных первому методу, может быть проще всего. (Конечно, могут быть и другие более простые методы, о которых я не знаю).
Изменить - сравнение этих двух методов:
При первом осмотре может показаться, что сферический треугольный подход является самым легким, но, в общем, это не так. Проблема в том, что нужно не только разбивать область на треугольники, но и на сферические треугольники, т.е. Треугольники, стороны которых являются большими дугами окружности. Например, широтные границы не квалифицируются, поэтому эти границы необходимо разбить на края, которые лучше приближают большие дуги окружности. И это становится труднее делать для произвольных ребер, где большие круги требуют определенных комбинаций сферических углов. Рассмотрим, например, как разбить среднюю полосу вокруг сферы, скажем, всю область между лат 0 и 45deg в сферические треугольники.
В конце концов, если нужно сделать это правильно с похожими ошибками для каждого метода, метод 2 даст меньше треугольников, но их будет сложнее определить. Метод 1 дает больше полос, но их тривиально определить. Поэтому я предлагаю метод 1 как лучший подход.
Ответ 2
Я переписал функцию "isaint" MATLAB в java, которая имеет точно такой же результат. "isaint" вычисляет "suface на единицу", поэтому я умножил ответ на Земную поверхность (5.10072e14 кв. м).
private double area(ArrayList<Double> lats,ArrayList<Double> lons)
{
double sum=0;
double prevcolat=0;
double prevaz=0;
double colat0=0;
double az0=0;
for (int i=0;i<lats.size();i++)
{
double colat=2*Math.atan2(Math.sqrt(Math.pow(Math.sin(lats.get(i)*Math.PI/180/2), 2)+ Math.cos(lats.get(i)*Math.PI/180)*Math.pow(Math.sin(lons.get(i)*Math.PI/180/2), 2)),Math.sqrt(1- Math.pow(Math.sin(lats.get(i)*Math.PI/180/2), 2)- Math.cos(lats.get(i)*Math.PI/180)*Math.pow(Math.sin(lons.get(i)*Math.PI/180/2), 2)));
double az=0;
if (lats.get(i)>=90)
{
az=0;
}
else if (lats.get(i)<=-90)
{
az=Math.PI;
}
else
{
az=Math.atan2(Math.cos(lats.get(i)*Math.PI/180) * Math.sin(lons.get(i)*Math.PI/180),Math.sin(lats.get(i)*Math.PI/180))% (2*Math.PI);
}
if(i==0)
{
colat0=colat;
az0=az;
}
if(i>0 && i<lats.size())
{
sum=sum+(1-Math.cos(prevcolat + (colat-prevcolat)/2))*Math.PI*((Math.abs(az-prevaz)/Math.PI)-2*Math.ceil(((Math.abs(az-prevaz)/Math.PI)-1)/2))* Math.signum(az-prevaz);
}
prevcolat=colat;
prevaz=az;
}
sum=sum+(1-Math.cos(prevcolat + (colat0-prevcolat)/2))*(az0-prevaz);
return 5.10072E14* Math.min(Math.abs(sum)/4/Math.PI,1-Math.abs(sum)/4/Math.PI);
}
Ответ 3
Вы упоминаете "географию" в одном из своих тегов, поэтому я могу только предположить, что вы находитесь за областью многоугольника на поверхности геоида. Обычно это делается с использованием проецируемой системы координат, а не географической системы координат (т.е. Lon/lat). Если бы вы сделали это в lon/lat, я бы предположил, что возвращаемая единица измерения будет составлять процент от поверхности сферы.
Если вы хотите сделать это с помощью более "ГИС", вам нужно выбрать единицу измерения для своей области и найти соответствующую проекцию, которая сохраняет область (не все). Поскольку вы говорите о вычислении произвольного многоугольника, я бы использовал что-то вроде проекция Lambert Azimuthal Equal Area. Задайте начало/центр проекции как центр вашего многоугольника, проецируйте многоугольник в новую систему координат, затем вычислите область с помощью стандартных планарных методов.
Если вам нужно сделать много полигонов в географической области, вероятны другие прогнозы, которые будут работать (или будут достаточно близки). Например, UTM является отличным приближением, если все ваши многоугольники группируются вокруг одного меридиана.
Я не уверен, что какое-либо из этого имеет какое-либо отношение к тому, как работает функция Matlab.
Ответ 4
Я ничего не знаю о функции Matlab, но здесь мы идем. Рассмотрим разбиение сферического многоугольника на сферические треугольники, например, вычерчивая диагонали из вершины. Площадь поверхности сферического треугольника определяется выражением
R^2 * ( A + B + C - \pi)
где R
- радиус сферы, а A
, B
, а C
- внутренние углы треугольника (в радианах). Величина в скобках известна как "сферический избыток".
Ваш n
-сторонний многоугольник будет разбит на треугольники n-2
. Суммируя по всем треугольникам, извлекая общий коэффициент R^2
и объединяя все \pi
, область вашего многоугольника
R^2 * ( S - (n-2)\pi )
где S
- это угловая сумма вашего многоугольника. Количество в круглых скобках снова является сферическим избытком многоугольника.
[edit] Это верно, является ли многоугольник выпуклым. Все, что имеет значение, состоит в том, что оно может быть разбито на треугольники.
Вы можете определить углы из бит векторной математики. Предположим, что у вас есть три вершины A
, B
, C
и интересуются углом at B
. Поэтому мы должны найти два касательных вектора (их величины не имеют значения) к сфере из точки B
вдоль больших круговых отрезков (краев многоугольника). Пусть это работает для BA
. Большой круг лежит в плоскости, определяемой OA
и OB
, где O
- центр сферы, поэтому он должен быть перпендикулярен нормальному вектору OA x OB
. Он также должен быть перпендикулярен к OB
, так как он касателен. Поэтому такой вектор задается выражением OB x (OA x OB)
. Вы можете использовать правильное правило, чтобы убедиться, что оно находится в соответствующем направлении. Обратите также внимание на то, что это упрощается до OA * (OB.OB) - OB * (OB.OA) = OA * |OB| - OB * (OB.OA)
.
Затем вы можете использовать хороший оловянный продукт, чтобы найти угол между сторонами: BA'.BC' = |BA'|*|BC'|*cos(B)
, где BA'
и BC'
- касательные векторы от B
вдоль сторон до A
и C
.
[отредактировано ясно, что это касательные векторы, а не буквальные между точками]