Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
программы.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
87.13 Кб
Скачать

27. Геометрические алгоритмы

Пересекаются ли 2 отрезка?

{ ------------------------------------------------------------------------ }

{ Определяет пересечение отрезков A(ax1,ay1,ax2,ay2) и B (bx1,by1,bx2,by2),}

{ функция возвращает TRUE - если отрезки пересекаются, а если пересекаются }

{ в концах или вовсе не пересекаются, возвращается FALSE (ложь)            }

{ ------------------------------------------------------------------------ }

function Intersection(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2:real):boolean;

var v1,v2,v3,v4:real;

begin

   v1:=(bx2-bx1)*(ay1-by1)-(by2-by1)*(ax1-bx1);

   v2:=(bx2-bx1)*(ay2-by1)-(by2-by1)*(ax2-bx1);

   v3:=(ax2-ax1)*(by1-ay1)-(ay2-ay1)*(bx1-ax1);

   v4:=(ax2-ax1)*(by2-ay1)-(ay2-ay1)*(bx2-ax1);

   Intersection:=(v1*v2<0) and (v3*v4<0);

end;

 

begin { основная программа, вызов функции - тест }

   writeln(Intersection(1,1,5,5,1,2,3,1)); {test1, yes Intersection}

   writeln(Intersection(1,1,5,5,1,2,1,3)); {test2, no  Intersection}

end.

Точка внутри сектора или нет?

{ ------------------------------------------------------------------------ }

{ Если точка внутри сектора (или на сторонах) - TRUE, если нет - FALSE     }

{ tx,ty - вершина сектора                                                  }

{ x1,y1,x2,y2 - точки на сторонах сектора                                  }

{ px,py - точка на плоскости                                               }

{                                                                          }

{ ------------------------------------------------------------------------ }

 

{возвращает знак числа, 1 - положительное число, -1 - отрицательное, 0 - 0 }

function sign(r:real):integer;

begin

     sign:=0; if r=0 then exit;

     if r<0 then sign:=-1 else sign:=1;

end;

 

function InsideSector(tx,ty,x1,y1,x2,y2,px,py:real):boolean;

var x,y,a1,a2,b1,b2,c1,c2:real;

var i1,i2,i3,i4:integer;

begin

  x:=(tx+x1+x2)/3; y:=(ty+y1+y2)/3;

  a1:=ty-y1; b1:=x1-tx; c1:=tx*y1-ty*x1;

  a2:=ty-y2; b2:=x2-tx; c2:=tx*y2-ty*x2;

  i1:=sign(a1*x+b1*y+c1); i2:=sign(a2*x+b2*y+b2);

  i3:=sign(a1*px+b1*py+c1); i4:=sign(a2*px+b2*py+c2);

  InsideSector:=((i1=i3) and (i2=i4)) or

                 ((i1=0) and (i2=i4)) or

                 ((i1=i3) and (i2=0));

end;

begin { основная программа, вызов функции - тест }

   writeln(InsideSector(1,1,5,1,1,5,3,3)); {test1, yes Inside}

   writeln(InsideSector(1,1,5,1,7,2,3,3)); {test2, no  Intersection}

end.

С какой стороны вектора лежит точка?

{ ------------------------------------------------------------------------ }

{ Если vector(a) и vector(b) - вектора a и b соответственно, то:           }

{                                                                          }

{ vector(a)*vector(b) = ax*by - ay*bx = a*b*sin(beta-alfa)                 }

{ ax,ay,bx,by - координаты концов векторов                                 }

{ a - длина вектора a                                                      }

{ b - длина вектора b                                                      }

{ alfa - угол альфа для вектора a                                          }

{ beta - угол бета для вектора b                                           }

{                                                                          }

{ Вывод: при общей начальной точке двух векторов их векторное произведение }

{        больше нуля, если второй вектор направлен влево от первого,       }

{        и меньше нуля, если вправо.                                       }

{                                                                          }

{ Если известны две точки, то вектор, основанный на них можно получить     }

{ вычитанием двух векторов направленных из начала координат:               }

{ Например, есть точка A и точка B                                         }

{ вектор|AB| = Вектор|B| - Вектор|A|, иным словом AB_x = Bx-Ax, AB_y= By-Ay}

{                                                                          }

{ Таким образом, получается:                                               }

{ Если есть вектор |AB|, заданный координатами ax,ay,bx,by и точка px,py,  }

{ то для того чтобы узнать лежит ли она слева или справа, надо узнать знак }

{ произведения:                                                            }

{ (bx-ax)*(py-ay)-(by-ay)*(px-ax)                                          }

{ ------------------------------------------------------------------------ }

 

var i:integer;

 

(* функция определеяет положение точки относительно вектора               *)

Function WherePoint(ax,ay,bx,by,px,py:real):integer;

var s :real;

begin

    s:=(bx-ax)*(py-ay)-(by-ay)*(px-ax);

    if s>0 then WherePoint:=1

    else if s<0 then WherePoint:=-1

    else WherePoint:=0;

end;

 

Begin (* Тело основной программы *)

   i:=WherePoint(1,1,8,8,2,5);

   if i > 0 then writeln('точка слева от вектора')

   else if i < 0 then writeln('точка справа от вектора')

   else writeln('на векторе, прямо по вектору или сзади вектора');

End.

С какой стороны вектора лежит точка? Вариант 1

{ ------------------------------------------------------------------------ }

{ Идея: обходим треугольник по часовой стрелке.                            }

{       Точка должна лежать справа от всех сторон, если она внутри         }

{ ------------------------------------------------------------------------ }

 

(* функция определеяет положение точки относительно вектора               *)

Function WherePoint(ax,ay,bx,by,px,py:real):integer;

var s :real;

begin

    s:=(bx-ax)*(py-ay)-(by-ay)*(px-ax);

    if s>0 then WherePoint:=1

    else if s<0 then WherePoint:=-1

    else WherePoint:=0;

end;

 

(* функция определеяет относительное положение точки: внутри или нет *)

Function PointInsideTreangle(ax,ay,bx,by,cx,cy,px,py:real):boolean;

var s1,s2,s3 :integer;

begin

    PointInsideTreangle:=FALSE;

    s1:=WherePoint(ax,ay,bx,by,px,py);

    s2:=WherePoint(bx,by,cx,cy,px,py);

    if s2*s1<=0 then EXIT;

    s3:=WherePoint(cx,cy,ax,ay,px,py);

    if s3*s2<=0 then EXIT;

    PointInsideTreangle:=TRUE;

end;

 

Begin (* Тело основной программы *)

   writeln(PointInsideTreangle(1,1,8,1,1,8,2,2)); {TEST1, Inside}

   writeln(PointInsideTreangle(1,1,8,1,1,8,6,6)); {TEST2, Outside}

End.

Точка внутри треугольника?  Вариант 2

{ ------------------------------------------------------------------------ }

{ Идея: Пусть есть треугольник ABC и точка P. Если Площадь ABC равна сумме }

{ площадей треугольников ABP,BCP,CAP, то точка внутри треугольника.        }

{ ------------------------------------------------------------------------ }

 

(* функция вычисляет расстояние между точками *)

Function Distance(ax,ay,bx,by:real):real;

begin

  Distance := sqrt(sqr(ax-bx)+sqr(ay-by));

end;

 

(* функция вычисляет площадь треугольника по формуле Герона *)

Function SqrGeron(ax,ay,bx,by,cx,cy:real):real;

var p,a,b,c :real;

Begin

  a:=Distance(cx,cy,bx,by);

  b:=Distance(ax,ay,cx,cy);

  c:=Distance(ax,ay,bx,by);

  p:=(a+b+c)/2;

  SqrGeron:=sqrt(p*(p-a)*(p-b)*(p-c));

End;

 

(* функция определеяет относительное положение точки: внутри или нет *)

Function PointInsideTreangle(ax,ay,bx,by,cx,cy,px,py:real):boolean;

const error = 1.000001;

var s,s1,s2,s3 :real;

begin

    PointInsideTreangle:=TRUE;

    s :=SqrGeron(ax,ay,bx,by,cx,cy);

    s1:=SqrGeron(ax,ay,bx,by,px,py);

    s2:=SqrGeron(bx,by,cx,cy,px,py);

    s3:=SqrGeron(cx,cy,ax,ay,px,py);

    if s*error>s1+s2+s3 then PointInsideTreangle:=TRUE

                        else PointInsideTreangle:=FALSE;

end;

 

Begin (* Тело основной программы *)

   writeln(PointInsideTreangle(1,1,8,1,1,8,2,2)); {TEST1, Inside}

   writeln(PointInsideTreangle(1,1,8,1,1,8,6,6)); {TEST2, Outside}

End.