Task

Draw a sphere.

The sphere can be represented graphically, or in ASCII art, depending on the language capabilities.

Either static or rotational projection is acceptable for this task.



Related tasks

 draw a cuboid
 draw a rotating cube
 write language name in 3D ASCII
 draw a Deathstar


 
(*
** 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] *)
 
(* ****** ****** *)
 