RosettaCodeData/Task/Draw-a-sphere/ATS/draw-a-sphere.ats

102 lines
2.7 KiB
Plaintext

(*
** Solution to Draw_a_sphere.dats
*)
(* ****** ****** *)
//
#include
"share/atspre_define.hats" // defines some names
#include
"share/atspre_staload.hats" // for targeting C
#include
"share/HATS/atspre_staload_libats_ML.hats" // for ...
#include
"share/HATS/atslib_staload_libats_libc.hats" // for libc
//
(* ****** ****** *)
extern
fun
Draw_a_sphere
(
R: double, k: double, ambient: double
) : void // end of [Draw_a_sphere]
(* ****** ****** *)
implement
Draw_a_sphere
(
R: double, k: double, ambient: double
) = let
fun normalize(v0: double, v1: double, v2: double): (double, double, double) = let
val len = sqrt(v0*v0+v1*v1+v2*v2)
in
(v0/len, v1/len, v2/len)
end // end of [normalize]
fun dot(v0: double, v1: double, v2: double, x0: double, x1: double, x2: double): double = let
val d = v0*x0+v1*x1+v2*x2
val sgn = gcompare_val_val<double> (d, 0.0)
in
if sgn < 0 then ~d else 0.0
end // end of [dot]
fun print_char(i: int): void =
if i = 0 then print!(".") else
if i = 1 then print!(":") else
if i = 2 then print!("!") else
if i = 3 then print!("*") else
if i = 4 then print!("o") else
if i = 5 then print!("e") else
if i = 6 then print!("&") else
if i = 7 then print!("#") else
if i = 8 then print!("%") else
if i = 9 then print!("@") else print!(" ")
val i_start = floor(~R)
val i_end = ceil(R)
val j_start = floor(~2 * R)
val j_end = ceil(2 * R)
val (l0, l1, l2) = normalize(30.0, 30.0, ~50.0)
fun loopj(j: int, j_end: int, x: double): void = let
val y = j / 2.0 + 0.5;
val sgn = gcompare_val_val<double> (x*x + y*y, R*R)
val (v0, v1, v2) = normalize(x, y, sqrt(R*R - x*x - y*y))
val b = pow(dot(l0, l1, l2, v0, v1, v2), k) + ambient
val intensity = 9.0 - 9.0*b
val sgn2 = gcompare_val_val<double> (intensity, 0.0)
val sgn3 = gcompare_val_val<double> (intensity, 9.0)
in
( if sgn > 0 then print_char(10) else
if sgn2 < 0 then print_char(0) else
if sgn3 >= 0 then print_char(8) else
print_char(g0float2int(intensity));
if j < j_end then loopj(j+1, j_end, x)
)
end // end of [loopj]
fun loopi(i: int, i_end: int, j: int, j_end: int): void = let
val x = i + 0.5
val () = loopj(j, j_end, x)
val () = println!()
in
if i < i_end then loopi(i+1, i_end, j, j_end)
end // end of [loopi]
in
loopi(g0float2int(i_start), g0float2int(i_end), g0float2int(j_start), g0float2int(j_end))
end
(* ****** ****** *)
implement
main0() = () where
{
val () = DrawSphere(20.0, 4.0, .1)
val () = DrawSphere(10.0, 2.0, .4)
} (* end of [main0] *)
(* ****** ****** *)