Автор Тема: Реализация некоторых геометрических конструкций  (Прочитано 1189 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн GodfatherАвтор темы

  • Старожил
  • ***
  • Сообщений 201
  • Респектов +1
  • Репутация 28
  • Пол: Мужской
    • Просмотр профиля
Доброго всем вечера. Думаю полезным может быть кому-нибудь следующая статья...)Сам я недавно столкнулся с проблемой реализации некоторых геометрических конструкций. Речь идет о декартовых координатах. Реализация будет производится в среде Pascal, но при нужде, добавлю на C++.
1) Уравнение прямой. По сути для вида y=kx+b проблем быть не должно. В принципе их недолжно быть и при переходе к 0=ax+by+c. Возьмем второй случай, а затем перейдем от него к первому.
Итак у нас есть две точки - A(x1,y1); B(x2,y2). Написать общее уравнение прямой. Обратимся к рисунку.
Очевидно, что для произвольной точки F(x,y) имеем LH/LI=FH/BI или
 . При чем  любое из четырех разностей может быть отрицательным. При перемножении получаем
Это общее уравнение прямой.

procedure LineCircle(alc,blc,clc,xolc,yolc,rlc: real; var xlc1,ylc1,xlc2,ylc2: real);
Begin
al:=yl1-yl2;
bl:=xl2-xl1;
cl:=-yl1*bl-xl1*al; {Здесь удобнее использовать именно такой вид, а не стандартный}
end;


2)Пересечение двух прямых. Задача, есть две прямые l1(a1x+b1y+c1) и l2(a2x+b2y+c2). Найти координаты точки пересечения. Проблем особо нет, если точка M(x,y), решаем систему двух уравнений. Откуда: . И соответственно:

procedure LineCircle(alc,blc,clc,xolc,yolc,rlc: real; var xlc1,ylc1,xlc2,ylc2: real);
Begin
if (atl1*btl2-atl2*btl1<>0) and (atl1*btl2-atl2*btl1<>0) then
Begin
xtl:=-(ctl1*btl2-ctl2*btl1)/(atl1*btl2-atl2*btl1);
ytl:=-(ctl2*atl1-ctl1*atl2)/(atl1*btl2-atl2*btl1);
end; {Проверка на равенство нулю проводится, потому что прямые могут быть параллельными}
end;


3)Прямая, перпендикулярная к данной. Задача. Есть прямая l(ax+by+c=0) и точка, M(x1,y1). Найти уравнение прямой, перпендикулярной данной. Задача стоит довольно простая, так как из школьного курса известно, что условие перпендикулярности двух прямых - произведение угловых коэффициентов равно нулю. Тогда, прямая l2 имеет уравнение: bx-ay+y1*a-x1*b=0


procedure Perp(ap1,bp1,cp1,xp,yp: real; var ap2,bp2,cp2: real);
Begin
ap2:=bp1;
bp2:=-ap1;
cp2:=ap1*yp-bp1*xp;
end;


4)Пересечение прямой и окружности. Задача. Есть прямая l(ax+by+c=0) и окружность, с центром O(xo,yo) и радиусом r. Найти координаты точки пересечения. В принципе можно решить квадратное уравнение, но это очень долго, так как решать придется не с одним параметром. Решим геометрически. Рассмотрим рисунок.

Возьмем для простоты, перенесем эту же окружность с прямой так, чтобы центр окружности оказался в начале координат. Тогда уравнение перенесенной прямой будет: ax+by+c+a*xo+b*yo=0; Тогда из 3-ей задачи, найдем уравнение прямой OH, а из 2-ой точку H.
Тогда расстояние OH выражается через теорему Пифагора.
 
Легко доказать подобие треугольников OHI и A1LH. Пусть m это отношение HI и OH. Тогда оно равно отношению LH к A1H. Тогда, A1H выражается через OH и радиус окружности по т. Пифагора. А LH - это модуль разности между xa1 и xh. Далее находим A1L - модуль разности игреков. В конце, добавим к полученным результатам координаты центра окружности, ведь мы смещали данную конструкцию.


procedure LineCircle(alc,blc,clc,xolc,yolc,rlc: real; var xlc1,ylc1,xlc2,ylc2: real);
var
hlc,ablc,mlc,x0lc,y0lc,dlc,o0a,o0b,o0c,ulc: real;
Begin
Perp(alc,blc,clc+alc*xolc+blc*yolc,0,0,o0a,o0b,o0c);{Находим уравнение перпендикулярной прямой}
TwoLines(alc,blc,clc+alc*xolc+blc*yolc,o0a,o0b,o0c,x0lc,y0lc); {Находим точку H(x0lc,y0lc)}
mlc:=abs(y0lc)/(sqrt(x0lc*x0lc+y0lc*y0lc)); {Выражаем m}
ablc:=sqrt(rlc*rlc-x0lc*x0lc-y0lc*y0lc); {Находим A1H}
hlc:=ablc*mlc; {Получаем LH}
ulc:=sqrt(ablc*ablc-hlc*hlc); {Получаем A1L}
xlc1:=xolc+x0lc+hlc;
xlc2:=xolc+x0lc-hlc;
if alc*blc>0 then {Выполняем проверку углового коэфициента, чтобы поставить правильные игреки}
Begin
ylc1:=yolc+y0lc-ulc;
ylc2:=yolc+y0lc+ulc;
end
else
Begin
ylc1:=yolc+y0lc+ulc;
ylc2:=yolc+y0lc-ulc;
end;
end;


5)Пересечение двух окружностей. Задача, есть две окружности с заданными центрами и радиусами. Найти точки их пересечения. Решим задачу опять геометрически.

Расстояние между центрами d найдем по расстоянию между двумя точками.

Пусть расстояния от центров окружностей до H будут a и b. Тогда d=a+b. Выразим a по теореме Пифагора

Тогда b=d-a. Через теорему Пифагора выражаем AH, пусть это будет h. Тогда можем по отношению d к a найти координаты точки H. Затем, по отношению d к b координаты искомых точек.


procedure TwoCircles(Xtc1,ytc1,xtc2,ytc2,Rtc1,Rtc2: real;var Xitc1,yitc1,xitc2,yitc2: real);
var
atc,btc,ctc,dtc,htc,x0tc,y0tc: real;
Begin
dtc:=sqrt(sqr(xtc2-xtc1)+sqr(ytc2-ytc1));
Btc:=(sqr(Rtc2)-sqr(Rtc1)+sqr(Dtc))/(2*Dtc);
Atc:=Dtc-Btc;
if (Atc<>0) and (Btc<>0) and (Htc<>0) and (DTC<>0) then
Begin
Htc:=sqrt(abs(sqr(Rtc2)-sqr(Btc)));
X0tc:=round(Xtc1+(Xtc2-Xtc1)/(Dtc/Atc));
Y0tc:=round(Ytc1+(Ytc2-Ytc1)/(Dtc/Atc));
Xitc1:=round(X0tc-(Y0tc-Ytc2)*Htc/Btc);
Yitc1:=round(Y0tc+(X0tc-Xtc2)*Htc/Btc);
Xitc2:=round(X0tc+(Y0tc-Ytc2)*Htc/Btc);
Yitc2:=round(Y0tc-(X0tc-Xtc2)*Htc/Btc);
end;
end;


Это основные конструкции, остальные опираются на данные. Но при желании можно будет скинуть и что-нибудь другое.

Форум аватар