88 lines
2.4 KiB
Ada
88 lines
2.4 KiB
Ada
package body Polygons is
|
|
EPSILON : constant := 0.00001;
|
|
|
|
function Ray_Intersects_Segment
|
|
(Who : Point;
|
|
Where : Segment)
|
|
return Boolean
|
|
is
|
|
The_Point : Point := Who;
|
|
Above : Point;
|
|
Below : Point;
|
|
M_Red : Float;
|
|
Red_Is_Infinity : Boolean := False;
|
|
M_Blue : Float;
|
|
Blue_Is_Infinity : Boolean := False;
|
|
begin
|
|
if Where (1).Y < Where (2).Y then
|
|
Above := Where (2);
|
|
Below := Where (1);
|
|
else
|
|
Above := Where (1);
|
|
Below := Where (2);
|
|
end if;
|
|
if The_Point.Y = Above.Y or The_Point.Y = Below.Y then
|
|
The_Point.Y := The_Point.Y + EPSILON;
|
|
end if;
|
|
if The_Point.Y < Below.Y or The_Point.Y > Above.Y then
|
|
return False;
|
|
elsif The_Point.X > Above.X and The_Point.X > Below.X then
|
|
return False;
|
|
elsif The_Point.X < Above.X and The_Point.X < Below.X then
|
|
return True;
|
|
else
|
|
if Above.X /= Below.X then
|
|
M_Red := (Above.Y - Below.Y) / (Above.X - Below.X);
|
|
else
|
|
Red_Is_Infinity := True;
|
|
end if;
|
|
if Below.X /= The_Point.X then
|
|
M_Blue := (The_Point.Y - Below.Y) / (The_Point.X - Below.X);
|
|
else
|
|
Blue_Is_Infinity := True;
|
|
end if;
|
|
if Blue_Is_Infinity then
|
|
return True;
|
|
elsif Red_Is_Infinity then
|
|
return False;
|
|
elsif M_Blue >= M_Red then
|
|
return True;
|
|
else
|
|
return False;
|
|
end if;
|
|
end if;
|
|
end Ray_Intersects_Segment;
|
|
|
|
function Create_Polygon (List : Point_List) return Polygon is
|
|
Result : Polygon (List'Range);
|
|
Side : Segment;
|
|
begin
|
|
for I in List'Range loop
|
|
Side (1) := List (I);
|
|
if I = List'Last then
|
|
Side (2) := List (List'First);
|
|
else
|
|
Side (2) := List (I + 1);
|
|
end if;
|
|
Result (I) := Side;
|
|
end loop;
|
|
return Result;
|
|
end Create_Polygon;
|
|
|
|
function Is_Inside (Who : Point; Where : Polygon) return Boolean is
|
|
Count : Natural := 0;
|
|
begin
|
|
for Side in Where'Range loop
|
|
if Ray_Intersects_Segment (Who, Where (Side)) then
|
|
Count := Count + 1;
|
|
end if;
|
|
end loop;
|
|
if Count mod 2 = 0 then
|
|
return False;
|
|
else
|
|
return True;
|
|
end if;
|
|
end Is_Inside;
|
|
|
|
end Polygons;
|