Имеется вектор в декартовой системе координат, как определить направлен он по часовой стрелке или против нее, относительно начала координат.
P.S. рисуется все на канве, соответственно начало координат - верхний левый угол канвы.
Модератор: Модераторы
— не корректна (скажем, если между двумя векторами ОДИН из углов = 90, это означает, что между ними 90 ПО ЧАСОВОЙ, или 270 ПРОТИВ?).направлен он по часовой стрелке или против нее
program p6;
var
X, Y, R,Angle,cos1,cos2:real;
begin
Write('X координата вектора ');
ReadLn(X);
Write('Y координата вектора ');
ReadLn(Y);
R:=sqrt(X*X+Y*Y);
if R=0 then begin
Write('Задан нулевой вектор');
Exit
end;
cos1:=X/R;
cos2:=Y/R;
if cos1=0 then Angle:=pi/2 else Angle:=arctan(sqrt(1-cos1*cos1)/cos1);
Angle:=Angle*180/pi;
if cos1>=0 then begin
if cos2>=0 then Angle:=90-Angle else Angle:=90+Angle
end else begin
if cos2>=0 then Angle:=-90-Angle else Angle:=-90+Angle
end;
WriteLn('Вектор направлен под углом=',Angle:0:2)
end.
{ calculates arctan(y/x) and returns an angle in the correct quadrant }
function arctan2(y,x : float) : float;
program p7;
type
pVertex=^TVertex;
TVertex=record
X, Y:real;
Next:pVertex
end;
var
Vertexes, tmp:pVertex;
v1x, v2x, v1y, v2y:real;
Angle:real;
State, NewState:ShortInt;
function ArcTan_2(y, x:real):Real;
var
sign:ShortInt;
begin
if y<0 then sign:=-1 else sign:=1;
if x=0 then Result:=sign*pi/2 else Result:=arctan(y/x);
if x<0 then Result:=Result+sign*pi
end;
function LoadVertexes(var Vertex:pVertex; fname:string):boolean;
var
VertexCount, Code, p:integer;
F:text;
tmp, tmp1:pVertex;
x, y:real;
s, s1:string;
begin
Result:=True;
if not(FileExists(fname)) then begin
WriteLn('Файл '+fName+' не существует');
Result:=False;
exit
end;
Assign(F, fName);
Reset(F);
VertexCount:=0;
tmp1:=Vertex;
While Not(eof(F)) do begin
ReadLn(f,s);
if s='' then continue;
p:=pos(';',s);
s1:=copy(s,1,p-1);
Delete(s,1,p);
Val(s1, x, Code);
if code<>0 then begin
WriteLn('Неверно задана переменная X');
Close(F);
Result:=False;
exit
end;
Val(s, y, Code);
if code<>0 then begin
WriteLn('Неверно задана переменная Y');
Close(F);
Result:=False;
exit
end;
if tmp1<>nil then if (tmp1^.X=X) and (tmp1^.Y=Y) then begin
WriteLn('Две заданные подряд вершины совпадают. Поэтому вторая пропускается.');
Continue
end;
inc(VertexCount);
New(tmp);
tmp^.X:=X;
tmp^.Y:=y;
{ tmp^.Next:=nil;
if Vertex=nil then Vertex:=tmp else tmp1^.Next:=tmp; // это если описываем не полигон, а ломанную линию
}
if Vertex=Nil then begin // а это для полигона ...
Vertex:=tmp;
tmp^.Next:=tmp
end else begin
tmp1^.Next:=tmp;
tmp^.Next:=Vertex
end; // ... (замкнутого контура)
tmp1:=tmp
end;
Close(F);
if VertexCount<3 then begin
WriteLn('В файле '+fName+' содержится описание менее 3 вершин');
Result:=False;
exit
end else WriteLn('Из файла '+fName+' загружено описание ',VertexCount,' вершин');
end;
begin
if not LoadVertexes(Vertexes, 'Vertexes.csv') then exit;
tmp:=Vertexes;
State:=0;
Repeat // для полигона
// while tmp^.Next^.Next<>Nil do begin // для ломаной
v1x:=tmp^.Next^.X-tmp^.X;
v1y:=tmp^.Next^.Y-tmp^.Y;
v2x:=tmp^.Next^.Next^.X-tmp^.Next^.X;
v2y:=tmp^.Next^.Next^.Y-tmp^.Next^.Y;
Angle:=ArcTan_2(v2y, v2x)-ArcTan_2(v1y, v1x);
if Angle>pi then Angle:=Angle-2*pi;
if Angle<-pi then Angle:=Angle+2*pi;
// writeln(Angle*180/pi); // для контроля
NewState:=0;
if (Angle>0) and (angle<pi) then NewState:=-1;
if (Angle<0) and (angle>-pi) then NewState:=1;
if NewState<>0 then begin
if State=0 then State:=NewState else if State<>NewState then begin
State:=0;
Break
end;
end;
tmp:=tmp^.Next
until tmp=Vertexes; // (замкнутого контура)
// end; // линии
if State=-1 then WriteLn('Последовательность обхода вершин - против часовой стрелки.');
if State=0 then WriteLn('Последовательность обхода вершин - не определена.');
if State=1 then WriteLn('Последовательность обхода вершин - по часовой стрелке.');
end.
1;1
0;2
1;3
2;2
1.5;1.5
program p8;
type
pVertex=^TVertex;
TVertex=record
X, Y:real;
Next:pVertex
end;
var
Vertexes, tmp:pVertex;
v1x, v2x, v1y, v2y:real;
Angle:real;
ClockWize, AntiClockWize:integer;
function ArcTan_2(y, x:real):Real;
var
sign:ShortInt;
begin
if y<0 then sign:=-1 else sign:=1;
if x=0 then Result:=sign*pi/2 else Result:=arctan(y/x);
if x<0 then Result:=Result+sign*pi
end;
function LoadVertexes(var Vertex:pVertex; fname:string):boolean;
var
VertexCount, Code, p:integer;
F:text;
tmp, tmp1:pVertex;
x, y:real;
s, s1:string;
begin
Result:=True;
if not(FileExists(fname)) then begin
WriteLn('Файл '+fName+' не существует');
Result:=False;
exit
end;
Assign(F, fName);
Reset(F);
VertexCount:=0;
tmp1:=Vertex;
While Not(eof(F)) do begin
ReadLn(f,s);
if s='' then continue;
p:=pos(';',s);
s1:=copy(s,1,p-1);
Delete(s,1,p);
Val(s1, x, Code);
if code<>0 then begin
WriteLn('Неверно задана переменная X');
Close(F);
Result:=False;
exit
end;
Val(s, y, Code);
if code<>0 then begin
WriteLn('Неверно задана переменная Y');
Close(F);
Result:=False;
exit
end;
if tmp1<>nil then if (tmp1^.X=X) and (tmp1^.Y=Y) then begin
WriteLn('Две заданные подряд вершины совпадают. Поэтому вторая пропускается.');
Continue
end;
inc(VertexCount);
New(tmp);
tmp^.X:=X;
tmp^.Y:=y;
{ tmp^.Next:=nil;
if Vertex=nil then Vertex:=tmp else tmp1^.Next:=tmp; // это если описываем не полигон, а ломанную линию
}
if Vertex=Nil then begin // а это для полигона ...
Vertex:=tmp;
tmp^.Next:=tmp
end else begin
tmp1^.Next:=tmp;
tmp^.Next:=Vertex
end; // ... (замкнутого контура)
tmp1:=tmp
end;
Close(F);
if VertexCount<3 then begin
WriteLn('В файле '+fName+' содержится описание менее 3 вершин');
Result:=False;
exit
end else WriteLn('Из файла '+fName+' загружено описание ',VertexCount,' вершин');
end;
begin
if not LoadVertexes(Vertexes, 'Vertexes.csv') then exit;
tmp:=Vertexes;
ClockWize:=0;
AntiClockWize:=0;
Repeat // для полигона
// while tmp^.Next^.Next<>Nil do begin // для ломаной
v1x:=tmp^.Next^.X-tmp^.X;
v1y:=tmp^.Next^.Y-tmp^.Y;
v2x:=tmp^.Next^.Next^.X-tmp^.Next^.X;
v2y:=tmp^.Next^.Next^.Y-tmp^.Next^.Y;
Angle:=ArcTan_2(v2y, v2x)-ArcTan_2(v1y, v1x);
if Angle>pi then Angle:=Angle-2*pi;
if Angle<-pi then Angle:=Angle+2*pi;
// writeln(Angle*180/pi); // для контроля
if (Angle>0) and (angle<pi) then inc(AntiClockWize);
if (Angle<0) and (angle>-pi) then inc(ClockWize);
tmp:=tmp^.Next
until tmp=Vertexes; // (замкнутого контура)
// end; // линии
if AntiClockWize+ClockWize>0 then WriteLn('Последовательность обхода вершин:',#10,'по часовой - ',100*ClockWize/(ClockWize+AntiClockWize),'%;',#10,'против часовой - ',100*AntiClockWize/(ClockWize+AntiClockWize),'%.')
else WriteLn('Последовательность обхода вершин - не определена.')
end.
Result := Result + (Mass[i+1].Y + Mass[i].Y)/2*(Mass[i+1].X-Mass[i].X)
//вычисление площади со знаком для произвольного многоугольника
function Square(Mass: TFigureMass): Real;
var
i: Integer;
begin
SetLength(Mass, Length(Mass)+1);
Mass[High(Mass)] := Mass[0]; //начало и конец массива совпадают
Result:=0;
for i := 0 to Length(Mass) - 2 do
Result := Result + (Mass[i+1].Y + Mass[i].Y)/2*(Mass[i+1].X-Mass[i].X)
end;
Вернуться в Обучение Free Pascal
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3