Bitmap/Bézier curves/Cubic: Difference between revisions
< Bitmap
Content added Content deleted
(added C) |
(Ada solution added) |
||
Line 5: | Line 5: | ||
=={{header|Ada}}== |
|||
<ada> |
|||
procedure Cubic_Bezier |
|||
( Picture : in out Image; |
|||
P1, P2, P3, P4 : Point; |
|||
Color : Pixel; |
|||
N : Positive := 20 |
|||
) is |
|||
Points : array (0..N) of Point; |
|||
begin |
|||
for I in Points'Range loop |
|||
declare |
|||
T : constant Float := Float (I) / Float (N); |
|||
A : constant Float := (1.0 - T)**3; |
|||
B : constant Float := 3.0 * T * (1.0 - T)**2; |
|||
C : constant Float := 3.0 * T**2 * (1.0 - T); |
|||
D : constant Float := T**3; |
|||
begin |
|||
Points (I).X := Positive (A * Float (P1.X) + B * Float (P2.X) + C * Float (P3.X) + D * Float (P4.X)); |
|||
Points (I).Y := Positive (A * Float (P1.Y) + B * Float (P2.Y) + C * Float (P3.Y) + D * Float (P4.Y)); |
|||
end; |
|||
end loop; |
|||
for I in Points'First..Points'Last - 1 loop |
|||
Line (Picture, Points (I), Points (I + 1), Color); |
|||
end loop; |
|||
end Cubic_Bezier; |
|||
</ada> |
|||
The following test |
|||
<ada> |
|||
X : Image (1..16, 1..16); |
|||
begin |
|||
Fill (X, White); |
|||
Cubic_Bezier (X, (16, 1), (1, 4), (3, 16), (15, 11), Black); |
|||
Print (X); |
|||
</ada> |
|||
should produce output: |
|||
<pre> |
|||
HH |
|||
HH HH |
|||
H H |
|||
H H |
|||
H H |
|||
H H |
|||
H H |
|||
H H |
|||
H H |
|||
H H |
|||
H H |
|||
H |
|||
</pre> |
|||
=={{header|C}}== |
=={{header|C}}== |
||
Line 56: | Line 110: | ||
#undef plot |
#undef plot |
||
#undef line</C> |
#undef line</C> |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
Revision as of 14:37, 6 December 2008
Bitmap/Bézier curves/Cubic
You are encouraged to solve this task according to the task description, using any language you may know.
You are encouraged to solve this task according to the task description, using any language you may know.
Using the data storage type defined on this page for raster images, and the draw_line
function defined in this other one, draw a cubic bezier curves
(definition on Wikipedia).
Ada
<ada> procedure Cubic_Bezier
( Picture : in out Image; P1, P2, P3, P4 : Point; Color : Pixel; N : Positive := 20 ) is Points : array (0..N) of Point;
begin
for I in Points'Range loop declare T : constant Float := Float (I) / Float (N); A : constant Float := (1.0 - T)**3; B : constant Float := 3.0 * T * (1.0 - T)**2; C : constant Float := 3.0 * T**2 * (1.0 - T); D : constant Float := T**3; begin Points (I).X := Positive (A * Float (P1.X) + B * Float (P2.X) + C * Float (P3.X) + D * Float (P4.X)); Points (I).Y := Positive (A * Float (P1.Y) + B * Float (P2.Y) + C * Float (P3.Y) + D * Float (P4.Y)); end; end loop; for I in Points'First..Points'Last - 1 loop Line (Picture, Points (I), Points (I + 1), Color); end loop;
end Cubic_Bezier; </ada> The following test <ada>
X : Image (1..16, 1..16);
begin
Fill (X, White); Cubic_Bezier (X, (16, 1), (1, 4), (3, 16), (15, 11), Black); Print (X);
</ada> should produce output:
HH HH HH H H H H H H H H H H H H H H H H H H H
C
<C>#define plot(x, y) put_pixel_clip(img, x, y, r, g, b)
- define line(x0,y0,x1,y1) draw_line(img, x0,y0,x1,y1, r,g,b)
void cubic_bezier(
image img, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int x3, unsigned int y3, unsigned int x4, unsigned int y4, color_component r, color_component g, color_component b )
{
unsigned int i; double pts[N_SEG+1][2]; for (i=0; i <= N_SEG; ++i) { double t = (double)i / (double)N_SEG;
double a = pow((1.0 - t), 3.0); double b = 3.0 * t * pow((1.0 - t), 2.0); double c = 3.0 * pow(t, 2.0) * (1.0 - t); double d = pow(t, 3.0);
double x = a * x1 + b * x2 + c * x3 + d * x4; double y = a * y1 + b * y2 + c * y3 + d * y4; pts[i][0] = x; pts[i][1] = y; }
- if 0
/* draw only points */ for (i=0; i <= N_SEG; ++i) { plot( pts[i][0], pts[i][1] ); }
- else
/* draw segments */ for (i=0; i < N_SEG; ++i) { int j = i + 1;
line( pts[i][0], pts[i][1],
pts[j][0], pts[j][1] ); }
- endif
}
- undef plot
- undef line</C>
OCaml
<ocaml>let cubic_bezier ~img ~color
~p1:(_x1, _y1) ~p2:(_x2, _y2) ~p3:(_x3, _y3) ~p4:(_x4, _y4) = let x1, y1, x2, y2, x3, y3, x4, y4 = (float _x1, float _y1, float _x2, float _y2, float _x3, float _y3, float _x4, float _y4) in let bz t = let a = (1.0 -. t) ** 3.0 and b = 3.0 *. t *. ((1.0 -. t) ** 2.0) and c = 3.0 *. (t ** 2.0) *. (1.0 -. t) and d = t ** 3.0 in let x = a *. x1 +. b *. x2 +. c *. x3 +. d *. x4 and y = a *. y1 +. b *. y2 +. c *. y3 +. d *. y4 in (int_of_float x, int_of_float y) in let rec loop _t acc = if _t > 20 then acc else begin let t = (float _t) /. 20.0 in let x, y = bz t in loop (succ _t) ((x,y)::acc) end in let pts = loop 0 [] in
(* (* draw only points *) List.iter (fun (x, y) -> put_pixel img color x y) pts; *)
(* draw segments *) let line = draw_line ~img ~color in let by_pair li f = let rec aux prev = function | [] -> () | x::xs -> f prev x; aux x xs in aux (List.hd li) (List.tl li) in by_pair pts (fun p0 p1 -> line ~p0 ~p1);
- </ocaml>