+ Ellipse rendering (orthogonal)
This commit is contained in:
parent
f24d519d77
commit
1891961f63
|
@ -1,5 +1,10 @@
|
|||
with Video.Integer_Geometry;
|
||||
use type Video.Integer_Geometry.Point;
|
||||
use Video.Integer_Geometry;
|
||||
|
||||
with Ada.Text_IO;
|
||||
use Ada.Text_IO;
|
||||
with Ada.Integer_Text_IO;
|
||||
use Ada.Integer_Text_IO;
|
||||
|
||||
package body Video.Rasters.Generic_Blits is
|
||||
|
||||
|
@ -92,7 +97,95 @@ package body Video.Rasters.Generic_Blits is
|
|||
Target (Center.Y - S, Center.X + C) := Color;
|
||||
Target (Center.Y - S, Center.X - C) := Color;
|
||||
end loop;
|
||||
end;
|
||||
end Circle;
|
||||
|
||||
procedure Ellipse (
|
||||
Color : in Pixel;
|
||||
Target : in out Raster;
|
||||
Bounds : in Integer_Geometry.Box)
|
||||
is
|
||||
X, Y : Coordinate; -- Offset from center in half-pixels
|
||||
D : Coordinate; -- Deviation from ideal ellipse
|
||||
A, B : Coordinate; -- Axis lengths
|
||||
S : Coordinate;
|
||||
procedure Draw is
|
||||
XS : constant Coordinate := Bounds.X.First + Bounds.X.Last;
|
||||
YS : constant Coordinate := Bounds.Y.First + Bounds.Y.Last;
|
||||
begin
|
||||
Target ((YS + Y) / 2, (XS + X) / 2) := Color;
|
||||
Target ((YS + Y) / 2, (XS - X) / 2) := Color;
|
||||
Target ((YS - Y) / 2, (XS + X) / 2) := Color;
|
||||
Target ((YS - Y) / 2, (XS - X) / 2) := Color;
|
||||
end;
|
||||
begin
|
||||
if Is_empty (Bounds) then
|
||||
return; -- No pixels to draw
|
||||
end if;
|
||||
|
||||
A := Length (Bounds.X); -- +1 to have 1/2 pixel offset
|
||||
B := Length (Bounds.Y);
|
||||
|
||||
-- Horizontal part
|
||||
if A mod 2 = 0 then
|
||||
Target (Center (Bounds.Y), Bounds.X.First) := Color;
|
||||
Target (Center (Bounds.Y), Bounds.X.Last) := Color;
|
||||
X := 0;
|
||||
else
|
||||
X := -1;
|
||||
end if;
|
||||
|
||||
Y := B;
|
||||
|
||||
-- D := ((DX * B)**2 + (DY * A)**2 - A**2 * B) / 4;
|
||||
D := ((X * B)**2) / 4; -- + 2 is for rounding
|
||||
while (X + 1) * B**2 < (Y - 1) * A**2 loop
|
||||
D := D + (X + 1) * B**2;
|
||||
X := X + 2;
|
||||
pragma Assert (D = (X * B)**2 + (Y * A)**2 - A**2 * B**2);
|
||||
-- Step Y -> Y - 2
|
||||
-- D(i) = ((X * B)**2 + ( Y * A)**2 - A**2 * B**2) / 4
|
||||
-- D(i+1) = ((X * B)**2 + ((Y - 2) * A)**2 - A**2 * B**2) / 4
|
||||
-- D(i+1) - D(i) = (((Y - 2) * A)**2) / 4 - ((Y * A)**2) / 4
|
||||
-- = A**2 * (1 - Y)
|
||||
S := (1 - Y) * A**2;
|
||||
-- Step down when its deviation is of opposite sign and less in abs. value
|
||||
if (D + S / 2) >= 0 then
|
||||
Y := Y - 2;
|
||||
D := D + S;
|
||||
pragma Assert (D = (X * B)**2 + (Y * A)**2 - A**2 * B**2);
|
||||
end if;
|
||||
Draw;
|
||||
end loop;
|
||||
|
||||
while Y > 0 loop
|
||||
D := D + (1 - Y) * A**2;
|
||||
Y := Y - 2;
|
||||
pragma Assert (D = (X * B)**2 + (Y * A)**2 - A**2 * B**2);
|
||||
-- Step X -> X + 2
|
||||
-- D(i) = (( X * B)**2 + (Y * A)**2 - A**2 * B**2) / 4
|
||||
-- D(i+1) = (((X + 2) * B)**2 + (Y * A)**2 - A**2 * B**2) / 4
|
||||
-- D(i+1) - D(i) = (((X + 2) * B)**2) / 4 - ((X * B)**2) / 4
|
||||
-- = B**2 * (X + 1)
|
||||
S := (X + 1) * B**2;
|
||||
if (D + S / 2) < 0 then
|
||||
X := X + 2;
|
||||
D := D + S;
|
||||
pragma Assert (D = (X * B)**2 + (Y * A)**2 - A**2 * B**2);
|
||||
end if;
|
||||
Draw;
|
||||
end loop;
|
||||
|
||||
-- Vertical part
|
||||
if B mod 2 = 0 then
|
||||
Target (Bounds.Y.First, Center (Bounds.X)) := Color;
|
||||
Target (Bounds.Y.Last, Center (Bounds.X)) := Color;
|
||||
end if;
|
||||
|
||||
end Ellipse;
|
||||
|
||||
-- Ellipse equation:
|
||||
-- (X - Xc)²/A² + (Y - Yc)²/B² = 1
|
||||
-- in integers:
|
||||
-- (X - Xc)² B² + (Y - Yc)² A² = A² B²
|
||||
|
||||
end Video.Rasters.Generic_Blits;
|
||||
|
|
|
@ -23,4 +23,10 @@ package Video.Rasters.Generic_Blits is
|
|||
Center : in Integer_Geometry.Point;
|
||||
Radius : in Natural);
|
||||
|
||||
procedure Ellipse (
|
||||
Color : in Pixel;
|
||||
Target : in out Raster;
|
||||
Bounds : in Integer_Geometry.Box);
|
||||
-- Note: Ellipse is actually drawn one pixel off Bounds, because it defines zero-thickness ellipse.
|
||||
|
||||
end Video.Rasters.Generic_Blits;
|
||||
|
|
|
@ -45,4 +45,13 @@ package body Video.Rasters.Generic_Renderers.Color is
|
|||
Target.Circle (Center, Radius, From_Color (Color));
|
||||
end Circle;
|
||||
|
||||
procedure Ellipse (
|
||||
Target : in out Color_Renderer;
|
||||
Bounds : in Integer_Geometry.Box;
|
||||
Color : in Colors.Color)
|
||||
is
|
||||
begin
|
||||
Target.Ellipse (Bounds, From_Color (Color));
|
||||
end Ellipse;
|
||||
|
||||
end Video.Rasters.Generic_Renderers.Color;
|
||||
|
|
|
@ -31,4 +31,9 @@ package Video.Rasters.Generic_Renderers.Color is
|
|||
Radius : in Natural;
|
||||
Color : in Colors.Color);
|
||||
|
||||
procedure Ellipse (
|
||||
Target : in out Color_Renderer;
|
||||
Bounds : in Integer_Geometry.Box;
|
||||
Color : in Colors.Color);
|
||||
|
||||
end Video.Rasters.Generic_Renderers.Color;
|
||||
|
|
|
@ -59,4 +59,13 @@ package body Video.Rasters.Generic_Renderers is
|
|||
Blits.Circle (Paint, Target.Target.all, Center, Radius);
|
||||
end Circle;
|
||||
|
||||
procedure Ellipse (
|
||||
Target : in out Renderer;
|
||||
Bounds : in Integer_Geometry.Box;
|
||||
Paint : in Pixel)
|
||||
is
|
||||
begin
|
||||
Blits.Ellipse (Paint, Target.Target.all, Bounds);
|
||||
end Ellipse;
|
||||
|
||||
end Video.Rasters.Generic_Renderers;
|
||||
|
|
|
@ -37,4 +37,9 @@ package Video.Rasters.Generic_Renderers is
|
|||
Radius : in Natural;
|
||||
Paint : in Pixel);
|
||||
|
||||
procedure Ellipse (
|
||||
Target : in out Renderer;
|
||||
Bounds : in Integer_Geometry.Box;
|
||||
Paint : in Pixel);
|
||||
|
||||
end Video.Rasters.Generic_Renderers;
|
||||
|
|
|
@ -53,6 +53,12 @@ begin
|
|||
Rend.Circle ((Screen_Width / 2, Screen_Height / 2), X * 10,
|
||||
Color => Video.Colors.Hex_6 (16#FF00FF#));
|
||||
end loop;
|
||||
|
||||
for X in 0 .. 10 loop
|
||||
Rend.Ellipse (((Screen_Width / 2 - X * 20, Screen_Width / 2 + X * 20),
|
||||
(Screen_Height / 2 - 200 + X * 20, Screen_Height / 2 + 200 - X * 20)),
|
||||
Color => Video.Colors.Hex_6 (16#00FFFF#));
|
||||
end loop;
|
||||
end;
|
||||
|
||||
declare
|
||||
|
|
Loading…
Reference in New Issue