Вычисление постоянного азимута и длины линии румба между двумя точками для геодезических координат

Материал из GIS-Lab
Версия от 17:23, 20 августа 2012; Bolotoved (обсуждение | вклад) (Новая страница: «{{Статья|Опубликована|angles-rhumb}} {{Аннотация|Решения задачи нахождения постоянного азимута…»)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигации Перейти к поиску
Эта страница опубликована в основном списке статей сайта
по адресу http://gis-lab.info/qa/angles-rhumb.html


Решения задачи нахождения постоянного азимута (вдоль линии румба), используемый код может применяться в других расширениях.

Линия румба или локсодром - линия пересекающая меридианы под постоянным углом. Линия румба - прямая линия в проекции Меркатора, на сфере - линия румба представляет из себя сферическую спираль, сходящуюся концентрическими кругами к полюсам. Для того, чтобы вычислить угол линии румба между двумя произвольными точками, можно воспользоваться следующим скриптом.

Все параллели являются локсодромами, так как пересекают меридианы под постоянным углом 90 градусов.

Данный угол не равен углу т.н. начального азимута, т.е. углу, под которым надо выйти из начальной точки, чтобы потом, следуя по линии большого круга (то есть кратчайшим расстоянием) придти в конечную точку. При следовании по линии большого круга, направление постоянно изменяется.

Скачать пример расчета в Excel

Вычислениям приведенным выше соответствует следующий код на языке Avenue (координаты двух точек передаются отдельно, процедуру вызова скрипта расчета см. ниже) (скачать скрипт расчета азимута):

pi = 3.14159265358979
pi2 = Pi / 2
lat1 = pnt1.getY*pi/180
lat2 = pnt2.getY*pi/180
long1 = -1*pnt1.getX*pi/180
long2 = -1*pnt2.getX*pi/180
dlon_W = (long2 - long1) - (2*pi*(((long2 - long1)/(2*pi)).floor))
dlon_E = (long1 - long2) - (2*pi*(((long1 - long2)/(2*pi)).floor))
dphi = ((((lat2/2) + (pi/4)).tan)/(((lat1/2) + (pi/4)).tan)).ln

if ((lat2 - lat1).abs < 0.00000001) then
     q = lat1.cos
else
     q = (lat2 - lat1)/dphi
end

if (dlon_W < dlon_E) Then
     dlon_W = -1*dlon_W
     'get sign
     if (dlon_W >= 0) then
        sign = 1
     else
        sign = -1
     end
  If ((dlon_W.abs) >= (dphi.abs)) Then
     Atn2 = (sign * pi2) - (dphi / dlon_W).atan
  Else
     If (dphi > 0) Then
        Atn2 = (dlon_W / dphi).atan
     Else
        If ((-1*dlon_W) >= 0) Then
           Atn2 = Pi + (dlon_W / dphi).atan
        Else
           Atn2 = (-1*Pi) + (dlon_W / dphi).atan
        End
     End
  End
else
   'get sign
   if (dlon_W >= 0) then
      sign = 1
   else
      sign = -1
   end
   If ((dlon_E.abs) >= (dphi.abs)) Then
      Atn2 = sign * pi2 - (dphi / (dlon_E)).atan
   Else
      If (dphi > 0) Then
         Atn2 = ((dlon_E) / dphi).atan
      Else
         If ((dlon_E) >= 0) Then
            Atn2 = Pi + ((dlon_E) / dphi).atan
         Else
            Atn2 = (-1*Pi) + ((dlon_E) / dphi).atan
         End
      End
   End
dlon = dlon_E end tc = atn2 - (2*pi*(((atn2)/(2*pi)).floor)) dist = ((q^2)*(dlon^2) + ((lat2-lat1)^2)).sqrt 'результат - угол в градусах tcdeg = (tc*180)/pi 'результат - расстояние в метрах distm = dist*6372795 reslist = {tcdeg, distm} return reslist

Для вызова процедуры расчета азимутов приведенной выше, можно воспользоваться следующим скриптом, результатом его работы будет расчет азимутов от точки testpont на все точки активной темы вида и запись результата в поле Newang атрибутивной таблицы этой темы:

atheme = av.getactivedoc.getactivethemes.get(0)
aftab = atheme.getftab
f_shape = aftab.findfield("Shape")
f_ang = aftab.findfield("Loxang")
f_dist = aftab.findfield("Loxdist")

'testpoint - точка отсчета
testpoint = point.make(25.85, 55.15)
aftab.seteditable(true)

'для каждой точки темы на которые считаем азимуты от точки отсчета
for each rec in aftab
	pnts = {}
	apoint = aftab.returnvalue(f_shape, rec)
	pnts.add(apoint.getx)
	pnts.add(testpoint.getx)
	pnts.add(apoint.gety)
	pnts.add(testpoint.gety)

	'Вызов процедуры расчета азимута
	'"Calc-azimuth" - название скрипта с процедурой в проекте
	loxval = av.run("Calc-azimuth", pnts)
	aftab.setvalue(f_ang, rec, loxval.get(0))
	aftab.setvalue(f_dist, rec, loxval.get(1))
end
aftab.seteditable(false)

Следует обратить особое внимание на порядок исходной и конечной точки, т.е. точки от которой берется азимут и точки на которую он берется, если получаемые значения представляют собой 180 + угол или 180 - угол - попробуйте поменять местами входные широты и долготы, порядок в данном случае имеет значение. Например поменяв фрагмент предыдущего скрипта следующим образом:

'...
	pnts.add(testpoint.getx)
	pnts.add(apoint.getx)
	pnts.add(testpoint.gety)
	pnts.add(apoint.gety)
'...

Ссылки по теме