Простите avis, возможно, это повторный пост, но на всякий случай...
Если Вам это ещё нужно, то вот что я набросал:
Код: Выделить всё
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.
в файле Vertexes.csv хранятся вершины (X и Y координаты через точку с запятой, по одной вершине в строчке), прмерно так:
Вроде работает.
С уважением, Алексей.
P.S.
В порядке прикола:
Код: Выделить всё
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.