Hosted by
|
with Messages; use Messages;
with Outlines; use Outlines;
with Lines; use Lines;
with Cubics; use Cubics;
with Real_Vectors; use Real_Vectors;
package body Curves is
function Make_Cubic_With_Coefficients
(D, C, B, A : in Vector)
return Line_Access
is
Control_A : Vector := D + C / 3.0;
Control_B : Vector := Control_A + (C + B) / 3.0;
To : Vector := D + C + B + A;
begin
return Create(To => To,
Control_A => Control_A,
Control_B => Control_B);
end Make_Cubic_With_Coefficients;
function Make_Cubic_Through_Points
(F0 : in Vector;
F1 : in Vector;
F2 : in Vector;
F3 : in Vector)
return Line_Access
is
X0 : Vector := (0.0, 0.0);
X1 : Vector := (1.0 / 3.0, 1.0 / 3.0);
X2 : Vector := (2.0 / 3.0, 2.0 / 3.0);
X3 : Vector := (1.0, 1.0);
F01 : Vector := 3.0 * (F1 - F0);
F12 : Vector := 3.0 * (F2 - F1);
F23 : Vector := 3.0 * (F3 - F2);
F012 : Vector := 1.5 * (F12 - F01);
F123 : Vector := 1.5 * (F23 - F12);
F0123 : Vector := 1.0 * (F123 - F012);
D : Vector := F0;
C : Vector := F01 - (X1) * F012 + (X1 * X2) * F0123;
B : Vector := F012 - X1 * F0123 - X2 * F0123;
A : Vector := F0123;
begin
return Make_Cubic_With_Coefficients(D, C, B, A);
end Make_Cubic_Through_Points;
function Make_Cubic_From_Slopes
(P0, P1, P2 : in Vector)
return Line_Access is
begin
return Create(Control_A => P1, Control_B => P1, To => P2);
end Make_Cubic_From_Slopes;
procedure Make_Cubic
(Start : in Vector;
A, B : access Line'Class;
Result : out Line_Access;
Error : out Real)
is
Length_A : Real := Length(Start, A);
Length_B : Real := Length(A.To, B);
Length_Both : Real := Length_A + Length_B;
Part_A : Real := Length_A / Length_Both;
function Way_Point
(Part : in Real)
return Vector is
begin
if Part < Part_A
then return Way_Point(Start, A, Part * Length_Both / Length_A);
else return Way_Point(A.To, B, (Part - Part_A) * Length_Both / Length_B);
end if;
end Way_Point;
Interpolate_A : Vector := Way_Point(1.0 / 3.0);
Interpolate_B : Vector := Way_Point(2.0 / 3.0);
Part : Real;
begin
Result := Make_Cubic_Through_Points(Start, Interpolate_A, Interpolate_B, B.To);
Result.Length := Length_Both;
Error := 0.0;
for Index in 1 .. 24 loop
Part := Real(Index * 2 - 1) / 48.0;
Error := Real'Max(Error, abs(Way_Point(Part) - Way_Point(Start, Result, Part)));
end loop;
end Make_Cubic;
procedure Make_Cubic
(This : access Outline;
Tolerance : in Real)
is
use Line_Lists;
Item_1 : Item_Access := Last_Item(This);
Item_2 : Item_Access := First_Item(This);
Item_3 : Item_Access := Next_Item(Item_2);
Item_4 : Item_Access := Next_Item(Item_3);
Stop : Item_Access := Item_3;
Counter : Natural := 2;
Line_1, Line_2, Line_3, Line_4 : Line_Access;
|