В задаче прямого зондирования ионосферы находятся такие частота и угол зондирования, при которых переданный сигнал достигает приемник (рис. 1).
Рис. 1. Траектория луча в системе координат зондирования
На рис. 1 использованы следующие обозначения:
x, y - оси координат системы координат зондирования (СКЗ);
α - угол зондирования;
h0 - начальная высота ионосферы;
R - радиус Земли;
P0, P1, P2 и P3 - соответственно точки расположения источника сигнала, входа луча в ионосферу, выхода луча из ионосферы и пересечения луча с поверхностью Земли.
Траектория луча, отображающего сигнал, состоит из следующих трех частей:
S01 - от источника до входа в ионосферу;
S12 - путь в ионосфере;
S23 - от точки выхода из ионосферы к точке пересечения луча с поверхностью Земли.
Эта траектория называется групповым путем.
Траектория луча в ионосфере определяется в результате решения системы дифференциальных уравнений. Первый и последний участки - это отрезки прямых линий, соединяющие точки, координаты которых определяются в программе решения задачи прямого зондирования ионосферы (далее ПЗИ). (Координаты источника задаются на входе программы.)
Задача состоит в том, чтобы по созданным в ПЗИ данным отобразить групповой путь, а также представить в виде градиентной заливки массив квадратов плазменной частоты (КПЧ) зондируемой области ионосферы (используется карта Gradient).
Этот массив создается в ПЗИ по используемой модели ионосферы и содержит значения КПЧ в узловых точках исследуемой области ионосферы(рис. 2).
Рис. 2. Узловые точки отражающего слоя ионосферы со значениями квадратов плазменной частоты
Для получения результата в ПЗИ вносится код, обеспечивающий вывод в текстовый файл массива КПЧ, координат точек P0, P1. P2 и P3, а также массив координат точек, проходимых лучом в ионосфере.
Далее полученные файлы читаются MAXScript-программой и отображаются в среде 3ds Max.
В ПЗИ добавляется подпрограмма вывода в текстовые файлы данных, необходимых для воспроизведения группового пути и градиентной заливки исследуемой области ионосферы:
!
! Выводит данные, необходимые для отображения группового пути
! и градиентной заливки ионосферы зондируемой области ионосферы
subroutine mgMpGrpPthDt()
integer i, j
! Файл с параметрами сигнала и координатами узловых точек
open(21, file = 'ntPntsXY.txt')
! Угол и частота зондирования и угол между источником и приемником
write(21, '(3f15.2)') prbNgl, prbFrqnc, , 180.0_8 * srcRcvrNgl / pi
! Число точек по углу и высоте
write(21, '(2i5)') nNgl, nH
! Массив с координатами узловых точек
write(21, '(2f15.2)') arrXY
! Файл со значениями КПЧ в узловых точках
open(22, file = 'ntPntsF2N.txt')
write(22, '(f15.2)') arrF2N
! Файл со значениями координат точки P3 пересечения луча и Земли (см. рис. 1)
! и координат точек на траектории луча в ионосфере
open(23, file = 'p3Crdnts.txt')
write(23, '(2f15.2)') crssngCrds
! Число точек на траектории луча в ионосфере
write(23, '(i8)') nBmPntsTKp
! Точки траектории луча в ионосфере
write(23, '(2f15.2)') arrBmPnts(1:nBmPntsTKp)
end subroutine mgMpGrpPthDt
При составлении подпрограммы учтено, что
Координаты точек на траектории луча заданы в СКЗ (см. рис. 1). Начальная часть файла p3Crdnts.txt:
1095.61 -94.93 (Координаты точки P3)
7966 (Число точек на траектории луча в ионосфере)
463.24 73.37 (Координаты точек на траектории луча)
463.24 73.37
463.50 73.41
463.64 73.43
463.84 73.46
464.73 73.60
465.03 73.65
Приводимая ниже программа строит групповой путь непосредственно по имеющимся в файле значениям в СКЗ. Если имеющийся в программе флаг shwSR установлен (равен истине), выводятся оси координат и часть дуги, проходящей по поверхности Земли через источник и приемник (рис. 3).
Рис. 3. Групповой путь
Если флаг сброшен, то отображается только расположенная в ионосфере часть группового пути (рис. 4).
Рис. 4. Находящаяся в ионосфере часть группового пути
Для уменьшения объема вывода строки файла с координатами группового пути берутся с некоторым, задаваемым в программе шагом stp.
fn addNS pt0 pt pt2 clr drm = (
local s
s = line pos:pt0 wireColor:clr render_displayRenderMesh:drm render_thickness:1
addNewSpline s
if drm then (
addKnot s 1 #smooth #curve pt
addKnot s 1 #smooth #curve pt2
)
else (
addKnot s 1 #corner #line pt
addKnot s 1 #corner #line pt2
)
updateShape s
return s
)
fn arrSTNt s = (
local arrS, cnt
arrS = filterString s " "
cnt = arrS.count
return for k = 1 to cnt collect arrS[k] as float
)
delete $*
arrFls = getFiles "g:\\wkNd\\p3Crdnts.txt"
arrFls2 = getFiles "g:\\wkNd\\ntPntsXY.txt"
if arrFls.count > 0 and arrFls.count > 0 then (
-- The Earth radius
rRth = 6370
clr = black
r = 5
stp = 100
pt0 = [0, 0, 0]
-- Show source and receiver
shwSR = off
-- prbNgl - probe angle
fs = openFile arrFls2[1]
arrS = arrSTNt (readLine fs)
-- prbNgl - probe angle
prbNgl = arrS[1]
-- srcRcvrNgl - angle between source and receiver
srcRcvrNgl = arrS[3]
dNgl = 0.1 * srcRcvrNgl
close fs
fs = openFile arrFls[1]
arrS = arrSTNt (readLine fs)
pt3 = [arrS[1], arrS[2], 0]
nS = readLine fs as integer
s = readLine fs
s2 = ""
if shwSR do (
arrS1 = arrSTNt s
-- Line from source to entrance point
addNS pt0 pt0 [arrS1[1], arrS1[2], 0] red off
-- Coordinates axis
xs = addNS pt0 pt0 [arrS1[1], arrS1[2], 0] clr off
rotate xs (eulerAngles 0 0 -prbNgl)
scale xs [1.5, 1.5, 1.0]
xs = addNS pt0 pt0 [arrS1[1], arrS1[2], 0] clr off
rotate xs (eulerAngles 0 0 (90.0 - prbNgl))
scale xs [0.4, 0.4, 1.0]
rc = arc radius:rRth from:(90.0 - srcRcvrNgl - dNgl) to:(90 + dNgl) pos:[0, -rRth, 0] wireColor:blue
rc.optimize = off
)
while not eof fs do (
for k2 = 1 to stp do (
s2 = readLine fs
if eof fs do exit
)
arrS = arrSTNt s
arrS2 = arrSTNt s2
addNS pt0 [arrS[1], arrS[2], 0] [arrS2[1], arrS2[2], 0] clr on
s = s2
)
if shwSR do (
-- Line from quit point to receiver
addNS pt0 [arrS[1], arrS[2], 0] pt3 red off
sphere radius:r pos:pt0 wireColor:green
sph = sphere radius:r pos:pt3 wireColor:green
sph.pivot = pt0
)
select $*
max tool zoomExtents
clearSelection()
)
else
messageBox("File not found: " + arrFls[1] + " or " arrFls2[1])
Зондируемая область ионосферы (см. рис. 2) отображается в виде множества трапеций (рис. 5).
Рис. 5. Полигоны зондируемой области ионосферы
Вершины трапеций находятся в узловых точках исследуемой области ионосферы, координаты которых берутся из файла ntPntsXY.txt.
Как и при выводе группового пути, используется система координат зондирования.
Каждой трапеции назначается стандартный материал с градиентной картой (задается на диффузионной компоненте материала). Вывод осуществляется в оттенках серого цвета. Значения интерполируемых цветов вычисляются для каждой трапеции по значениям КПЧ в ее вершинах.
Трапеция выводится в следующем порядке:
Рис. 6. Вывод и градиентная заливка одной трапеции
Вывод одной трапеции обеспечивает функция nPlgn.
--
fn nPlgn p1 p2 p3 p4 mtrl = (
p = (point3 (0.5 * (p1[1] + p4[1])) (0.5 * (p1[2] + p4[2])) 0)
pln = plane pos:p length:(p4[2] - p1[2]) width:(p4[1] - p1[1]) lengthSegs:1 widthSegs:1 material:mtrl
convertToPoly pln
pln.verts[2].pos = p2
pln.verts[3].pos = p3
)
-- Test for function nPlgn
delete $*
x = 40
x2 = 30
y = 20
p1 = [-x, -y, 0]
p2 = [x, -y, 0]
p3 = [-x2, y, 0]
p4 = [x2, y, 0]
grdnt = gradient color1:black color2:white color2Pos:0.0
mtrl = standard diffuseMap:grdnt showInViewport:on
nPlgn p1 p2 p3 p4 mtrl
Вывод всех полигонов осуществляется по координатам узловых точек, хранимым в файле ntPntsXY.txt. Для сокращения размерности задачи выводимые полигоны укрупняются (регулируется параметрами stpH и stpNgl). Кроме того, пропускается часть начальных и конечных (по углу) трапеций (регулируется параметром dNgl).
--
-- Вывод без заливки полигонального представления зондируемой области ионосферы
fn nPlgn p1 p2 p3 p4 mtrl = (
p = (point3 (0.5 * (p1[1] + p4[1])) (0.5 * (p1[2] + p4[2])) 0)
pln = plane pos:p length:(p4[2] - p1[2]) width:(p4[1] - p1[1]) lengthSegs:1 widthSegs:1
if mtrl == undefined then
pln.wireColor = black
else
pln.material = mtrl
convertToPoly pln
pln.verts[2].pos = p2
pln.verts[3].pos = p3
)
fn arrSTNt s = (
local arrS, cnt
arrS = filterString s " "
cnt = arrS.count
return for k = 1 to cnt collect arrS[k] as float
)
fn getArrFrmFl nH nNgl fs arr = (
nH1 = nH + 1
nNgl2 = nNgl + 2
for k = 1 to nH1 do (
arrNgl = #()
for k2 = 1 to nNgl2 do (
arrS = arrSTNt (readLine fs)
if k > 1 and k2 > 1 and k2 < nNgl2 do append arrNgl (point3 arrS[1] arrS[2] 0)
)
if k > 1 do append arr arrNgl
)
)
delete $*
arrFls = getFiles "g:\\wkNd\\ntPntsXY.txt"
if arrFls.count > 0 then (
fs = openFile arrFls[1]
skipToNextLine fs
-- nNgl & nH - angle and height points ammount
arrS = arrSTNt (readLine fs)
nNgl = arrS[1] as integer
nH = arrS[2] as integer
arrXY = #()
getArrFrmFl nH nNgl fs arrXY
stpH = 25
stpNgl = 1
dNgl = 7
nHS = nH - stpH
nNglS = nNgl - dNgl - stpNgl
mtrl = undefined
for k = 1 to nHS by stpH do
for k2 =dNgl to nNglS by stpNgl do (
p1 = arrXY[k][k2]
p2 = arrXY[k][k2 + stpNgl]
p3 = arrXY[k + stpH][k2]
p4 = arrXY[k + stpH][k2 + stpNgl]
nPlgn p1 p2 p3 p4 mtrl
)
select $*
max tool zoomExtents
clearSelection()
)
else
messageBox("File not found: " + arrFls[1])
Параметры color1 и color2 карты Gradient определяются по значениям КПЧ, хранимым в файле ntPntsF2N.txt. При этом максимальное значение КПЧ отвечает черному цвету, а минимальное - белому.
--
-- Вывод с заливкой полигонального представления зондируемой области ионосферы
fn nPlgn p1 p2 p3 p4 mtrl = (
p = (point3 (0.5 * (p1[1] + p4[1])) (0.5 * (p1[2] + p4[2])) 0)
pln = plane pos:p length:(p4[2] - p1[2]) width:(p4[1] - p1[1]) lengthSegs:1 widthSegs:1
if mtrl == undefined then
pln.wireColor = black
else
pln.material = mtrl
convertToPoly pln
pln.verts[2].pos = p2
pln.verts[3].pos = p3
)
fn arrSTNt s = (
local arrS, cnt
arrS = filterString s " "
cnt = arrS.count
return for k = 1 to cnt collect arrS[k] as float
)
fn getArrFrmFl nH nNgl fs crds arr = (
local nH1, nNgl2, arrS, k, k2, s
nH1 = nH + 1
nNgl2 = nNgl + 2
for k = 1 to nH1 do (
arrNgl = #()
for k2 = 1 to nNgl2 do (
s = readLine fs
arrS = arrSTNt s
if k > 1 and k2 > 1 and k2 < nNgl2 do
if crds then
append arrNgl (point3 arrS[1] arrS[2] 0)
else
append arrNgl arrS[1]
)
if k > 1 do append arr arrNgl
)
)
-- Finds color for Gradient map
fn fndClr arrF2N k k2 f2NMn cf = (
vl = (255.0 - cf * (arrF2N[k][k2] - f2NMn)) as integer
print arrF2N[k][k2]
return color vl vl vl
)
delete $*
arrFls = getFiles "g:\\wkNd\\ntPntsXY.txt"
arrFls2 = getFiles "g:\\wkNd\\ntPntsF2N.txt"
if arrFls.count > 0 and arrFls2.count > 0 then (
fs = openFile arrFls[1]
skipToNextLine fs
-- nNgl & nH - angle and height points ammount
arrS = arrSTNt (readLine fs)
nNgl = arrS[1] as integer
nH = arrS[2] as integer
arrXY = #()
getArrFrmFl nH nNgl fs true arrXY
close fs
fs = openFile arrFls2[1]
arrF2N = #()
getArrFrmFl nH nNgl fs false arrF2N
f2NMx = f2NMn = arrF2N[1][1]
for k = 1 to nH do (
f2NMx = amax (amax arrF2N[k]) f2NMx
f2NMn = amin (amin arrF2N[k]) f2NMn
)
cf = 255.0 / (f2NMx - f2NMn)
stpH = 25
stpNgl = 1
dNgl = 7
nHS = nH - stpH
nNglS = nNgl - dNgl - stpNgl
for k = 1 to nHS by stpH do
for k2 =dNgl to nNglS by stpNgl do (
p1 = arrXY[k][k2]
p2 = arrXY[k][k2 + stpNgl]
p3 = arrXY[k + stpH][k2]
p4 = arrXY[k + stpH][k2 + stpNgl]
grdnt = gradient color2Pos:0.0
grdnt.color1 = fndClr arrF2N (k + stpH) (k2 + stpNgl) f2NMn cf
grdnt.color2 = fndClr arrF2N k k2 f2NMn cf
nPlgn p1 p2 p3 p4 (standard diffuseMap:grdnt showInViewport:on)
)
select $*
max tool zoomExtents
clearSelection()
-- Результат приведен на рис. 7
)
else
messageBox("File not found: " + arrFls[1] + " or " + arrFls[2])
Рис. 7. Градиентная заливка полигонального представления зондируемой области ионосферы
Наблюдаемая регулярность объясняется тем, что использованы данные, сгенерированные с употреблением параболической модели ионосферы.
Программы, предусмотренные заданием, реализованы на языках Fortran (подпрограмма вывода данных параметрами зондирующего сигнала и характеристиками ионосферы) и MAXScript (ввод данных и отображение группового пути и градиентной заливки полигонального представления зондируемой области ионосферы).
Задача графического вывода решена в системе координат зондирования. Для сокращение размерности задачи заливки использовано укрупнение полигонов, покрывающих исследуемую область ионосферы.