В некоторых задачах на построение графики иногда требуется применить иное, нежели в декартовой системе координат соотношение между точками и/или геометрическими объектами, поэтому в таких задачах нередко применяется полярная система координат (см. Полярная система координат), в которой соотношения между объектами плоскости выражаются через радиусы (r) и углы (phi).
Так как недавно пришлось с этим столкнуться (при решении одной из задач), то я решил обобщить некоторый полученный мной опыт в использовании полярных координат.
Сначала для удобства пользования введем две функции, которые нам очень потребуются в дальнейшем – это процедуры polar_point(x,y,r,phi) и polar_line(x,y,r,phi):
procedure polar_line(x,y,r,phi) local xx,yy xx:=r*cos(dtor(phi)) yy:=r*sin(dtor(phi)) DrawLine(x,y,x+xx,y+yy) end procedure polar_point(x,y,r,phi) local xx,yy xx:=r*cos(dtor(phi)) yy:=r*sin(dtor(phi)) DrawPoint(x+xx,y+yy) end
Эти функции требуют четыре параметра: x,y – декартовы координаты точки, которую мы будем использовать в качестве “начала координат” и r,phi – длина радиуса из “начала координат” до точки, которую мы хотим построить, а также угол (phi) между полярным лучом и радиус-вектором (радиусом) в требуемую точку.
Функция polar_point строит точки, а функция polar_line строит линии (от точки “начала координат” до точки координаты которой выражены через радиус и угол). Еще у этих функций есть небольшой нюанс, связанный с их определением, в частности из-за использования в них функции dtor(), преобразующей градусы в радианы (стандартные тригонометрические функции Icon принимают аргумент в радианах) угол phi будет определяться в градусах, причем диапазон значений практически не ограничен.
Однако, что дает применение именно полярной системы координат? Многое, в частности, введение полярных координат позволяет рисовать некоторые интересные кривые и фигуры. Например, с помощью полярных координат можно построить “полярную розу” (которая описывается уравнением r(phi)=2*sin(4*phi):
procedure rose(x,y)
local i,r
i:=-360
while i<360 do {
r:=2*sin(dtor(4*i))
polar_point(x,y,50*r,50+i)
i+:=0.01
}
endгде x,y – декартовы координаты точки с которой начнет строится “роза”, которая выглядит вот так:
А если в процедуре rose заменить polar_point на polar_line (с теми же аргументами), то получится закрашенная роза:
С помощью полярной системы координат можно выводить на экран различные интересные кривые, которые замучаешься программировать в декартовых координатах (вот же раздолье для математиков), например, спираль Архимеда:
procedure spiral_l(x,y,n)
local i,r
i:=-360*n
while i<0 do {
r:=0.5+0.08*i
polar_point(x,y,r,i)
i+:=0.01
}
endгде x,y – декартовы координаты “начала координат” (точку (0,0) ставить не советую!), а n – число витков спирали. В данном случае получается левозакрученная спираль, которая выглядит вот так:
Для получения картинки была применена команда spiral_l(250,250,5), а вывод был в окно размером 500*500 пикселей. Чтобы получить правозакрученную спираль, необходимо немного исправить процедуру вычерчивающую спираль (а именно, изменить параметр i) – получаем следующую процедуру:
procedure spiral_r(x,y,n)
local i,r
i:=0
while i<360*n do {
r:=0.5+0.08*i
polar_point(x,y,r,i)
i+:=0.01
}
endЗапущенная с теми же аргументами функция spiral_r дает вот такую спираль:
Еще одна интересная штучка получилась, когда я слегка ошибся в формуле описания конических сечений (эллипса, гиперболы, параболы и т.п.). Вот, собственно, программный код процедуры с ошибкой:
procedure sun(x,y,l,e)
local i,r
i:=0
while i<360 do {
r:=l/(1-e*cos(i))
polar_point(x,y,r*50,i+50)
i+:=0.01
}
endА вот результат:
К сожалению, я не знаю, что обозначают в данном случае некоторые параметры (ибо не математик, а полученный график следствие просчета), но одно понятно точно, что здесь нужно качественное исследование (кто хочет займитесь, но результаты опишите в комментариях).
Этот график, кстати, говоря был получен вот такой командой – sun(250,250,2,0.6), но что еще более интересно, что если заменить polar_point в функции sun на polar_line, то получается закрашенное солнце:
Следущее, что я смог реализовать – это конические сечения, процедура построения которых выглядит так:
procedure axial(x,y,l,e)
local i,r,kk
i:=-360
while i<360 do {
kk:=e*cos(dtor(i))
r:=l/(1.0-kk)
polar_point(x,y,r*10,i+10)
i+:=0.01
}
endгде x,y – декартовы координаты точки, которая будет играть роль “начала координат”, l – фокальный параметр, e – эксцентрисет (если e>1 получиться гипербола; e=1, то получиться парабола; e=0, получиться окружность с радиусом l, и если e < 1, то получиться эллипс).
Вот так выглядит результат команды axial(250,250,2,0.6):
Также, ради интереса, я написал процедуры для отображение “полярной розы” (но уже с настраиваемыми параметрами), циссоиды, кардиоиды, а также для отображения улитки Паскаля, которые наряду с уже представленными кривыми, можно увидеть тут:
procedure polar_line(x,y,r,phi)
local xx,yx
xx:=r*cos(dtor(phi))
yy:=r*sin(dtor(phi))
DrawLine(x,y,x+xx,y+yy)
end
procedure polar_point(x,y,r,phi)
local xx,yx
xx:=r*cos(dtor(phi))
yy:=r*sin(dtor(phi))
DrawPoint(x+xx,y+yy)
end
procedure rose(x,y)
local i,r
i:=-360
while i<360 do {
r:=2*sin(dtor(4*i))
polar_point(x,y,50*r,50+i)
i+:=0.01
}
end
procedure rose_l(x,y)
local i,r
i:=-360
while i<360 do {
r:=2*sin(dtor(4*i))
polar_line(x,y,50*r,50+i)
i+:=0.01
}
end
procedure rose_m(x,y,a,b,c)
local i,r
i:=-360
while i<360 do {
r:=a*cos(dtor(b*i+c))
polar_line(x,y,50*r,50+i)
i+:=0.1
}
end
procedure spiral_l(x,y,n)
local i,r
i:=-360*n
while i<0 do {
r:=0.5+0.08*i
polar_point(x,y,r,i)
i+:=0.01
}
end
procedure spiral_r(x,y,n)
local i,r
i:=0
while i<360*n do {
r:=0.5+0.08*i
polar_point(x,y,r,i)
i+:=0.01
}
end
procedure sun(x,y,l,e)
local i,r
i:=0
while i<360 do {
r:=l/(1-e*cos(i))
polar_point(x,y,r*50,i+50)
i+:=0.01
}
end
procedure FillSun(x,y,l,e)
local i,r
i:=0
while i<360 do {
r:=l/(1-e*cos(i))
polar_line(x,y,r*50,i+50)
i+:=0.01
}
end
procedure axial(x,y,l,e)
local i,r,kk
i:=-360
while i<360 do {
kk:=e*cos(dtor(i))
r:=l/(1.0-kk)
polar_point(x,y,r*10,i+10)
i+:=0.01
}
end
procedure kardio(x,y,a)
local i,r
i:=-360
while i<360 do {
r:=2*a*(1-cos(dtor(i)))
polar_point(x,y,r*50,i+50)
i+:=0.01
}
end
procedure pascal(x,y,l,a)
local i,r
i:=0
while i<360 do {
r:=l-a*sin(dtor(i))
polar_point(x,y,r*50,i+50)
i+:=0.01
}
end
procedure cissoid(x,y,a)
local i,r,v
i:=-70
while i<70 do {
v:=sin(dtor(i))^2
r:=(2*v*a)/(cos(dtor(i)))
polar_point(x,y,r*50,i+50)
i+:=0.01
}
end






