# Draw a sphere

Draw a sphere
You are encouraged to solve this task according to the task description, using any language you may know.

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.

## 11l

Translation of: Python
V shades = [‘.’, ‘:’, ‘!’, ‘*’, ‘o’, ‘e’, ‘&’, ‘#’, ‘%’, ‘@’]

F dotp(v1, v2)
V d = dot(v1, v2)
R I d < 0 {-d} E 0.0

F draw_sphere(r, k, ambient, light)
L(i) Int(floor(-r)) .< Int(ceil(r) + 1)
V x = i + 0.5
V line = ‘’

L(j) Int(floor(-2 * r)) .< Int(ceil(2 * r) + 1)
V y = j / 2 + 0.5
I x * x + y * y <= r * r
V vec = normalize((x, y, sqrt(r * r - x * x - y * y)))
V b = dotp(light, vec) ^ k + ambient
V intensity = Int((1 - b) * (:shades.len - 1))
E
line ‘’= ‘ ’

print(line)

V light = normalize((30.0, 30.0, -50.0))
draw_sphere(20, 4, 0.1, light)
draw_sphere(10, 2, 0.4, light)
Output:
                               &&&&&&&&&&#######
&eeeeeeeeeeeeeeee&&&&&&#######%
&eoooo*******oooooooeeeee&&&&&########%
eoo****!!!!!!!!******oooooeeee&&&&&########%%
eoo**!!!!::::::::!!!!!*****ooooeeee&&&&&########%%%
eo**!!::::::...:::::::!!!!!***ooooeeee&&&&&########%%%%
eo*!!:::.............:::::!!!!***ooooeeee&&&&&########%%%%%
eo*!!:::.................::::!!!!***ooooeeee&&&&#########%%%%%%
eo*!!::....................::::!!!****oooeeee&&&&&#########%%%%%%
&o**!::......................::::!!!****oooeeee&&&&&##########%%%%%%%
&o**!::.......................::::!!!****oooeeee&&&&&##########%%%%%%%%
&oo*!!::.......................:::!!!!***ooooeeee&&&&&##########%%%%%%%%%
&eo*!!::.......................::::!!!****ooooeeee&&&&&##########%%%%%%%%%%
eo**!!::......................::::!!!!***ooooeeeee&&&&&##########%%%%%%%%%%
&eo**!!:::...................:::::!!!!****ooooeeee&&&&&###########%%%%%%%%%%%
eeo**!!::::................:::::!!!!!****ooooeeee&&&&&&###########%%%%%%%%%%%
&eeo***!!:::::...........::::::!!!!!****oooooeeee&&&&&&###########%%%%%%%%%%%%%
&eeoo**!!!!::::::::::::::::::!!!!!*****ooooeeeee&&&&&&############%%%%%%%%%%%%%
&eeooo***!!!!::::::::::::!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%%
&&eeooo***!!!!!!!!!!!!!!!!!!!******oooooeeeeee&&&&&&############%%%%%%%%%%%%%%%
&&eeeooo******!!!!!!!!!!********ooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%%
#&&eeeooooo******************oooooooeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%%
#&&&eeeeoooooooo******oooooooooooeeeeeee&&&&&&&&#############%%%%%%%%%%%%%%%%%%
##&&&&eeeeeooooooooooooooooooeeeeeeee&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%
##&&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&################%%%%%%%%%%%%%%%%%%%
####&&&&&&eeeeeeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%%
#####&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%%
%#######&&&&&&&&&&&&&&&&&&&&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%
%###########&&&&&&&&&&&&&#######################%%%%%%%%%%%%%%%%%%%%%%%%%
%############################################%%%%%%%%%%%%%%%%%%%%%%%%%%
%%#######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%#################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%#########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%#############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%

::...:::!!!*o
..............::!!*oo
..................::!!**ooe
.....................::!!**ooee
.......................::!!**ooee
........................::!!**oooee
.........................::!!**oooeee
:........................::!!!**oooeeee
........................::!!!**ooooeeee
:......................::!!!***oooeeeee
:....................:::!!!***oooeeeeee
!:.................:::!!!****oooeeeeeee
*!:::...........::::!!!!***ooooeeeeeeee
*!!!:::::::::::!!!!!****oooooeeeeeeee
o**!!!!!!!!!!!!!*****oooooeeeeeeeee
oo**************ooooooeeeeeeeeeee
eoooooooooooooooooeeeeeeeeeeeee
eeeooooooooeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeee



## Action!

INT ARRAY SinTab=[
0 4 9 13 18 22 27 31 36 40 44 49 53 58 62 66 71 75 79 83
88 92 96 100 104 108 112 116 120 124 128 132 136 139 143
147 150 154 158 161 165 168 171 175 178 181 184 187 190
193 196 199 202 204 207 210 212 215 217 219 222 224 226
228 230 232 234 236 237 239 241 242 243 245 246 247 248
249 250 251 252 253 254 254 255 255 255 256 256 256 256]

INT FUNC Sin(INT a)
WHILE a<0 DO a==+360 OD
WHILE a>360 DO a==-360 OD
IF a<=90 THEN
RETURN (SinTab(a))
ELSEIF a<=180 THEN
RETURN (SinTab(180-a))
ELSEIF a<=270 THEN
RETURN (-SinTab(a-180))
ELSE
RETURN (-SinTab(360-a))
FI
RETURN (0)

INT FUNC Cos(INT a)
RETURN (Sin(a-90))

PROC Ellipse(INT x0,y0,rx,ry)
INT i
CARD x
BYTE y

x=x0+rx*Sin(0)/256
y=y0+ry*Cos(0)/256
Plot(x,y)
FOR i=5 TO 360 STEP 5
DO
x=x0+rx*Sin(i)/256
y=y0+ry*Cos(i)/256
DrawTo(x,y)
OD
RETURN

PROC Main()
BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6 INT cx=[160],cy=[96],r=[90],r2 BYTE i Graphics(8+16) COLOR1=$0C
COLOR2=$02 Color=1 Ellipse(cx,cy,r,r) FOR i=10 TO 90 STEP 10 DO r2=r*Cos(i)/256 Ellipse(cx,cy,r,r2) Ellipse(cx,cy,r2,r) OD DO UNTIL CH#$FF OD
CH=$FF RETURN Output: ## Ada Library: GtkAda Translation from the C code at http://cairographics.org/samples/gradient Uses the Cairo component of GtkAda to create and save as png with Glib; use Glib; with Cairo; use Cairo; with Cairo.Png; use Cairo.Png; with Cairo.Pattern; use Cairo.Pattern; with Cairo.Image_Surface; use Cairo.Image_Surface; with Ada.Numerics; procedure Sphere is subtype Dub is Glib.Gdouble; Surface : Cairo_Surface; Cr : Cairo_Context; Pat : Cairo_Pattern; Status_Out : Cairo_Status; M_Pi : constant Dub := Dub (Ada.Numerics.Pi); begin Surface := Create (Cairo_Format_ARGB32, 512, 512); Cr := Create (Surface); Pat := Cairo.Pattern.Create_Radial (230.4, 204.8, 51.1, 204.8, 204.8, 256.0); Cairo.Pattern.Add_Color_Stop_Rgba (Pat, 0.0, 1.0, 1.0, 1.0, 1.0); Cairo.Pattern.Add_Color_Stop_Rgba (Pat, 1.0, 0.0, 0.0, 0.0, 1.0); Cairo.Set_Source (Cr, Pat); Cairo.Arc (Cr, 256.0, 256.0, 153.6, 0.0, 2.0 * M_Pi); Cairo.Fill (Cr); Cairo.Pattern.Destroy (Pat); Status_Out := Write_To_Png (Surface, "SphereAda.png"); pragma Assert (Status_Out = Cairo_Status_Success); end Sphere;  Library: Display This uses a very loose binding to SDL as found in any GPS installation. For it to work, you must choose New Project From Templte|Empty Game with Display; use Display; with Display.Basic; use Display.Basic; procedure Main is Ball : Shape_Id := New_Circle (X => 0.0, Y => 0.0, Radius => 20.0, Color => Blue); begin null; end Main;  ## ALGOL W Translation of: AWK with some changes inspired by other samples. begin % draw a sphere % % returns the next integer larger than x or x if x is an integer % integer procedure ceil( real value x ) ; begin integer tmp; tmp := truncate( x ); if tmp not = x then tmp + 1 else tmp end ciel ; % returns the absolute value of the dot product of x and y or 0 if it is not negative % real procedure dot( real array x, y ( * ) ) ; begin real tmp; tmp := x( 1 ) * y( 1 ) + x( 2 ) * y( 2 ) + x( 3 ) * y( 3 ); if tmp < 0 then - tmp else 0 end dot ; % normalises the vector v % procedure normalize( real array v ( * ) ) ; begin real tmp; tmp := sqrt( v( 1 ) * v( 1 ) + v( 2 ) * v( 2 ) + v( 3 ) * v( 3 ) ); for i := 1 until 3 do v( i ) := v( i ) / tmp end normalize ; % draws a sphere using ASCII art % procedure drawSphere( real value radius ; integer value k ; real value ambient ; real array light ( * ) ; string(10) value shades ) ; begin real array vec ( 1 :: 3 ); integer intensity, maxShades; real diameter, r2; maxShades := 9; diameter := 2 * radius; r2 := radius * radius; for i := entier( - radius ) until ceil( radius ) do begin real x, x2; integer linePos; string(256) line; linePos := 0; x := i + 0.5; x2 := x * x; line := ""; for j := entier( - diameter ) until ceil( diameter ) do begin real y, y2; y := j / 2 + 0.5; y2 := y * y; if x2 + y2 <= r2 then begin real b, dp; vec( 1 ) := x; vec( 2 ) := y; vec( 3 ) := sqrt( r2 - x2 - y2 ); normalize( vec ); dp := dot( light, vec ); b := dp; for p := 2 until k do b := b * dp; b := b + ambient; intensity := round( ( 1 - b ) * maxShades ); if intensity < 0 then intensity := 0; if intensity > maxShades then intensity := maxShades; line( linePos // 1 ) := shades( intensity // 1 ); end else line( linePos // 1 ) := " " ; if linePos < 255 then linePos := linePos + 1 end for_j ; write( s_w := 0, line( 0 // 1 ) ); for c := 1 until if linePos > 255 then 255 else linePos - 1 do writeon( s_w := 0, line( c // 1 ) ) end for_i end drawSphere ; % test drawSphere % begin real array light ( 1 :: 3 ); integer maxShades; light( 1 ) := 30; light( 2 ) := 30; light( 3 ) := -59; normalize( light ); drawSphere( 20, 4, 0.1, light, ".:!*oe#%&@" ); drawSphere( 10, 2, 0.4, light, ".:!*oe#%&@" ) end test end. Output:  %%%%%%%%%%%%%&&&& %%#################%%%%%%%&&&&& %##eeeeeooooooeeeeeee######%%%%%%&&&&&& ##eeooooo*******oooooooeeeee####%%%%%%&&&&&&& ##eooo*****!!!!!!!******oooooeeee####%%%%%%&&&&&&&& #eeoo**!!!!!!!:::!!!!!!!*****ooooeeee####%%%%%&&&&&&&&& #eoo**!!!:::::::::::::::!!!!****ooooeeee####%%%%%%&&&&&&&&& #eeo**!!!::::.........::::::!!!!***ooooeeee####%%%%%%&&&&&&&&&& #eoo*!!!:::..............:::::!!!!***ooooeee#####%%%%%&&&&&&&&&&& %#eo**!!:::..................::::!!!****oooeeee####%%%%%%&&&&&&&&&&&& %#eo**!!:::...................::::!!!!***oooeeee####%%%%%%&&&&&&&&&&&&& %#eo**!!:::....................::::!!!!***oooeeee####%%%%%%&&&&&&&&&&&&&& %#eoo**!!::.....................::::!!!****oooeeee####%%%%%%&&&&&&&&&&&&&&& #eeo**!!:::....................::::!!!!***ooooeeee####%%%%%%&&&&&&&&&&&&&&& %#eoo**!!::::..................::::!!!!****oooeeee#####%%%%%%&&&&&&&&&&&&&&&& ##eoo**!!!::::...............:::::!!!!****ooooeeee####%%%%%%%&&&&&&&&&&&&&&&& %##eoo***!!!:::::..........::::::!!!!!****ooooeeee#####%%%%%%%&&&&&&&&&&&&&&&&& %##eeoo**!!!!::::::::::::::::::!!!!!*****ooooeeee#####%%%%%%%&&&&&&&&&&&&&&&&&& %##eeooo***!!!!!::::::::::::!!!!!!*****ooooeeeee#####%%%%%%%&&&&&&&&&&&&&&&&&&& %##eeeooo****!!!!!!!!!!!!!!!!!!******oooooeeeee#####%%%%%%%&&&&&&&&&&&&&&&&&&&& %%##eeeooo******!!!!!!!!!!!********oooooeeeee######%%%%%%%&&&&&&&&&&&&&&&&&&&&& %%###eeeooooo******************oooooooeeeeee######%%%%%%%&&&&&&&&&&&&&&&&&&&&&& &%%###eeeeooooooo*********oooooooooeeeeee#######%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&& &%%%####eeeeeooooooooooooooooooeeeeeeee#######%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&& &%%%%####eeeeeeeeeeeeeeeeeeeeeeeeee########%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&& &&%%%%#######eeeeeeeeeeeeeeeee##########%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&&&& &&%%%%%%############################%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&%%%%%%%#####################%%%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&%%%%%%%%%%%%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&& !!::::!!!**oo :...........:::!!**oe :.................::!!*ooee :....................::!!**ooee ......................::!!**ooeee ........................::!!**ooeee :........................::!!**ooeeee !........................::!!!**ooeeeee :.......................:::!!**oooeeeee :......................:::!!***ooeeeeee !:....................:::!!***oooeeeeee *!:.................:::!!!***oooeeeeeee o*!:::..........:::::!!!***ooooeeeeeeee o*!!!:::::::::::!!!!!***ooooeeeeeeeee o***!!!!!!!!!!!!*****ooooeeeeeeeeee eoo*************ooooooeeeeeeeeeee eeoooooooooooooooeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeee  ## Arendelle [ #j , [ #i , { ( #x - 19 ) ^ 2 + ( #y - 14 ) ^ 2 < 125 , p } r ] [ #i , l ] d ] ## ATS (* ** 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] *) (* ****** ****** *)  ## AutoHotkey Library: GDIP #NoEnv SetBatchLines, -1 #SingleInstance, Force ; Uncomment if Gdip.ahk is not in your standard library #Include, Gdip.ahk ; Settings X := 200, Y := 200, Width := 200, Height := 200 ; Location and size of sphere rotation := -30 ; degrees ARGB := 0xFFFF0000 ; Color=Solid Red If !pToken := Gdip_Startup() ; Start gdi+ { MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system ExitApp } OnExit, Exit Gui, -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs ; Create GUI Gui, Show, NA ; Show GUI hwnd1 := WinExist() ; Get a handle to this window we have created in order to update it later hbm := CreateDIBSection(A_ScreenWidth, A_ScreenHeight) ; Create a gdi bitmap drawing area hdc := CreateCompatibleDC() ; Get a device context compatible with the screen obm := SelectObject(hdc, hbm) ; Select the bitmap into the device context pGraphics := Gdip_GraphicsFromHDC(hdc) ; Get a pointer to the graphics of the bitmap, for use with drawing functions Gdip_SetSmoothingMode(pGraphics, 4) ; Set the smoothing mode to antialias = 4 to make shapes appear smother Gdip_TranslateWorldTransform(pGraphics, X, Y) Gdip_RotateWorldTransform(pGraphics, rotation) ; Base ellipse pBrush := Gdip_CreateLineBrushFromRect(0, 0, Width, Height, ARGB, 0xFF000000) Gdip_FillEllipse(pGraphics, pBrush, 0, 0, Width, Height) ; First highlight ellipse pBrush := Gdip_CreateLineBrushFromRect(Width*0.1, Height*0.01, Width*0.8, Height*0.6, 0x33FFFFFF, 0x00FFFFFF) Gdip_FillEllipse(pGraphics, pBrush, Width*0.1, Height*0.01, Width*0.8, Height*0.6) ; Second highlight ellipse pBrush := Gdip_CreateLineBrushFromRect(Width*0.3, Height*0.02, Width*0.3, Height*0.2, 0xBBFFFFFF, 0x00FFFFFF) Gdip_FillEllipse(pGraphics, pBrush, Width*0.3, Height*0.02, Width*0.3, Height*0.2) UpdateLayeredWindow(hwnd1, hdc, 0, 0, A_ScreenWidth, A_ScreenHeight) SelectObject(hdc, obm) ; Select the object back into the hdc Gdip_DeletePath(Path) Gdip_DeleteBrush(pBrush) DeleteObject(hbm) ; Now the bitmap may be deleted DeleteDC(hdc) ; Also the device context related to the bitmap may be deleted Gdip_DeleteGraphics(G) ; The graphics may now be deleted Return Exit: ; gdi+ may now be shutdown on exiting the program Gdip_Shutdown(pToken) ExitApp  ## AWK # syntax: GAWK -f DRAW_A_SPHERE.AWK # converted from VBSCRIPT BEGIN { draw_sphere(20,4,0.1) draw_sphere(10,2,0.4) exit(0) } function draw_sphere(radius,k,ambient, b,i,intensity,j,leng_shades,light,line,shades,vec,x,y) { leng_shades = split0(".:!*oe&#%@",shades,"") split("30,30,-50",light,",") normalize(light) for (i=int(-radius); i<=ceil(radius); i++) { x = i + 0.5 line = "" for (j=int(-2*radius); j<=ceil(2*radius); j++) { y = j / 2 + 0.5 if (x*x + y*y <= radius*radius) { vec[1] = x vec[2] = y vec[3] = sqrt(radius*radius - x*x - y*y) normalize(vec) b = dot(light,vec) ^ k + ambient intensity = int((1-b) * leng_shades) if (intensity < 0) { intensity = 0 } if (intensity >= leng_shades) { intensity = leng_shades } line = line shades[intensity] } else { line = line " " } } printf("%s\n",line) } } function ceil(x, tmp) { tmp = int(x) return (tmp != x) ? tmp+1 : tmp } function dot(x,y, tmp) { tmp = x[1]*y[1] + x[2]*y[2] + x[3]*y[3] return (tmp < 0) ? -tmp : 0 } function normalize(v, tmp) { tmp = sqrt(v[1]*v[1] + v[2]*v[2] + v[3]*v[3]) v[1] /= tmp v[2] /= tmp v[3] /= tmp } function split0(str,array,fs, arr,i,n) { # same as split except indices start at zero n = split(str,arr,fs) for (i=1; i<=n; i++) { array[i-1] = arr[i] } return(n) }  Output:  ############%%%%% #&&&eeeeeeeee&&&&&&#####%%%%%%% &eeeoooooooooooooeeeee&&&&#####%%%%%%%% &eoo***************oooooeeee&&&&####%%%%%%%%% &eo***!!!!!:::!!!!!!!****ooooeee&&&&#####%%%%%%%%%% eoo*!!!::::::::::::::!!!!****oooeeee&&&#####%%%%%%%%%%% eo**!!:::............::::!!!!***oooeeee&&&#####%%%%%%%%%%%% &eo*!!::.................:::!!!!***oooeee&&&&#####%%%%%%%%%%%%% eo*!!::...................::::!!!***oooeeee&&&#####%%%%%%%%%%%%%% #eo*!!::.....................:::!!!***oooeeee&&&&####%%%%%%%%%%%%%%%@ &eo*!!::......................:::!!!***oooeeee&&&&#####%%%%%%%%%%%%%%%@ &eo*!!::......................::::!!!***oooeeee&&&&#####%%%%%%%%%%%%%%%@@ #eo**!!::......................:::!!!****oooeee&&&&#####%%%%%%%%%%%%%%%%%@@ &eo**!:::....................::::!!!!***oooeeee&&&&#####%%%%%%%%%%%%%%%%%@@ &eoo**!!::...................::::!!!!***ooooeee&&&&######%%%%%%%%%%%%%%%%%@@@ &eoo**!!:::................::::!!!!****ooooeee&&&&&#####%%%%%%%%%%%%%%%%%%@@@ #&eoo**!!!::::...........:::::!!!!!****oooeeee&&&&&######%%%%%%%%%%%%%%%%%%@@@@ #&eeoo**!!!!::::::::::::::::!!!!!****ooooeeee&&&&&######%%%%%%%%%%%%%%%%%%%@@@@ #&eeooo***!!!!!::::::::!!!!!!!*****ooooeeeee&&&&&######%%%%%%%%%%%%%%%%%%%@@@@@ #&&eeooo****!!!!!!!!!!!!!!!******oooooeeee&&&&&#######%%%%%%%%%%%%%%%%%%%%@@@@@ ##&&eeoooo********************oooooeeeee&&&&&&######%%%%%%%%%%%%%%%%%%%%%%@@@@@ ##&&&eeeoooooo***********oooooooeeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%%%%@@@@@@ %##&&&eeeeeooooooooooooooooooeeeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@ %%###&&&&eeeeeeeeeeoeeeeeeeeeeee&&&&&&&&########%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@ %%###&&&&&&eeeeeeeeeeeeeeee&&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@ %%%#####&&&&&&&&&&&&&&&&&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@ %%%%#######&&&&&&&&&&&&&&&############%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@ %%%%%%#############################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@ %%%%%%%%######################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@ %%%%%%%%%%%%%%%#####%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@ @%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@ @@@@%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@ ::..::::!!**o .............::!!**oe ..................::!!*ooee .....................::!!*ooeee .......................:!!**ooeee ........................:!!**ooeeee ........................::!!**ooeeee& :........................::!!**ooeeee&& ........................::!!**oooeeee&& :......................::!!***ooeeeee&& :....................::!!!***ooeeeee&&& !::................:::!!***oooeeeeee&&& *!!::..........::::!!!****oooeeeeee&&&& **!!::::::::::!!!!!***ooooeeeeee&&&&& o***!!!!!!!!!!*****ooooeeeeeee&&&&& eooo*********ooooooeeeeeeee&&&&&& eeeoooooooooooeeeeeeeeee&&&&&&& eeeeeeeeeeeeeeeeeee&&&&&&&& &eeeeeeeeee&&&&&&&&&& &&&&&&&&&&&&&  ## BASIC ### BASIC256 This is based, but not exactly, on the Tcl implementation. Thus, the output is almost the same to the output of Tcl implementation below. clg color white rect 0,0,graphwidth, graphheight for n = 1 to 100 color rgb(2*n,2*n,2*n) circle 150-2*n/3,150-n/2,150-n next n ### BBC BASIC Using Direct3D.  MODE 8 INSTALL @lib$+"D3DLIB"
D3DTS_VIEW = 2
D3DTS_PROJECTION = 3
D3DRS_SPECULARENABLE = 29

#w "backcolor "; c$#w "place "; xS; " "; yS xS =xS -0.5 yS =yS -0.2 #w "circlefilled "; radius next radius #w "flush" wait close #w end ### Locomotive Basic Translated from ERRE version, this will print a 39x20 text sphere onscreen. The variables in line 80 can be used to adjust size (r), spotlight (k), reflective light (ambient). 10 MODE 2:s$=".:!*oe&#%@"
20 DIM v(2),vec(2)
30 v(0)=30:v(1)=30:v(2)=-50
40 lung=SQR(v(0)*v(0)+v(1)*v(1)+v(2)*v(2))
50 v(0)=v(0)/lung
60 v(1)=v(1)/lung
70 v(2)=v(2)/lung
80 r=10:k=2:ambient=0.4
90 FOR i=INT(-r) TO INT(r)
100 x=i+0.5
110 FOR j=INT(-2*r) TO INT(2*r)
120 y=j/2+0.5
130 IF (x*x+y*y<=r*r) THEN GOSUB 1000 ELSE PRINT" ";
140 NEXT j
150 PRINT
160 NEXT i
170 END
1000 vec(0)=x
1010 vec(1)=y
1020 vec(2)=SQR(r*r-x*x-y*y)
1030 GOSUB 2000
1040 GOSUB 3000
1050 b=d^k+ambient
END


### Run BASIC

'Run BASIC White Sphere, Black background
'runbasic.com
graphic #win, 300, 300
#win size(1)
R=100
R2=R*R
X0=300/2
Y0=300/2
for Y = -150 to 150
for X = -150 to 150
D2 = X*X + Y*Y
C = 0
if D2 <= R2 then Z = sqr(R2-D2) : C = int(Z-(X+Y)/2+130)
#win color(C,C,C)
#win set(X+X0, Y+Y0)
next X
next Y
render #win
'This is a simple Circle
graphic #g, 300, 300 	'create a graphic object
#g place(100,100) 	'place the drawing pen at 100,100
#g circle(75) 		'make a circle with radius 75
render #g 		'show it

### Sinclair ZX81 BASIC

Works with 1k of RAM. A screenshot of the output is here.

10 LET I=21
20 LET J=2
30 FOR K=-PI TO PI STEP 0.07
40 PLOT 21+I*SIN K,22+21*COS K
50 PLOT 21+21*SIN K,22+(I-1)*COS K
60 NEXT K
70 LET I=I-J
80 LET J=J+1
90 IF I>0 THEN GOTO 30


## Batch File

Translation of: C

Since Batch Files do not support floating point, the input parameters for drawing the sphere are limited to integers only. The k parameter has been hardcoded to 2. The ambient variable for this code is scaled up 10 times of its value in C implementation. For example, ambient = 0.1 in C code corresponds to ambient = 1 here. Lastly, the variables used in calculations are scaled up 100 times of the actual values in C implementation, and then scaled down 100 times back for determination of shades.

:: Draw a Sphere Task from Rosetta Code
:: Batch File Implementation

@echo off
rem -------------- define arithmetic "functions"

rem integer sqrt arithmetic function by Aacini, penpen and einstein1969
rem source: https://www.dostips.com/forum/viewtopic.php?f=3&t=5819&start=30#p44016
set "sqrt(N)=( M=(N),j=M/(11*1024)+40, j=(M/j+j)>>1, j=(M/j+j)>>1, j=(M/j+j)>>1, j=(M/j+j)>>1, j=(M/j+j)>>1, j+=(M-j*j)>>31 )"

rem -------------- define batch file macros with parameters appended
setlocal disabledelayedexpansion	% == required for macro ==%
(set \n=^^^
%== this creates escaped line feed for macro ==%
)

rem normalize macro
rem argument: v
set normalize=for %%# in (1 2) do if %%#==2 (  %\n%
for /f "tokens=1" %%a in ("!args!") do set "v=%%a"  %\n%
set /a "length_sqrd=!v![0]*!v![0]+!v![1]*!v![1]+!v![2]*!v![2]"  %\n%
set /a "length=%sqrt(N):N=!length_sqrd!%"  %== sqrt(N) applied ==%  %\n%
set /a "!v![0]*=100", "!v![1]*=100", "!v![2]*=100"  %== normalized elements mult. by 100 ==%  %\n%
set /a "!v![0]/=length", "!v![1]/=length", "!v![2]/=length"  %\n%
) else set args=

rem dot macro
rem arguments: s t outputvar
set dot=for %%# in (1 2) do if %%#==2 (  %\n%
for /f "tokens=1,2,3" %%a in ("!args!") do (  %\n%
set "s=%%a"  %\n%
set "t=%%b"  %\n%
set "outputvar=%%c"  %\n%
)  %\n%
set /a "d=!s![0]*!t![0]+!s![1]*!t![1]+!s![2]*!t![2]"  %\n%
if !d! lss 0 (set /a "!outputvar!=-d") else (set "!outputvar!=0")  %\n%
) else set args=

rem -------------- define pseudo-arrays
set "num_shades=9"  %== start at 0 ==%

set "light[0]=30" & set "light[1]=30" & set "light[2]=-50"

rem -------------- main thing: execute drawSphere
setlocal enabledelayedexpansion
%normalize% light  %== normalize macro applied ==%
call :drawSphere 20 1
exit /b 0

rem -------------- the function to draw the sphere
rem arguments: R ambient
:drawSphere
rem initialize variables from arguments
set /a "R=%1", "negR=-R", "twiceR=R*2", "twiceNegR=negR*2"
set /a "sqrdR=R*R*100*100"  %== R*R is mult. by 100*100 ==%
set "k=2"  %== k is hardcoded to 2 ==%
set "ambient=%2"
rem start draw line-by-line
for /l %%i in (%negR%, 1, %R%) do (
set /a "x=100*%%i+(100/2)"  %== x is mult. by 100 ==%
set "line="
for /l %%j in (%twiceNegR%, 1, %twiceR%) do (
set /a "y=(100/2)*%%j+(100/2)"  %== y is mult. by 100 ==%
set /a "pythag = x*x + y*y"
if !pythag! lss !sqrdR! (
set /a "vec[0]=x"
set /a "vec[1]=y"
set /a "vec[2]=sqrdR-pythag"
set /a "vec[2]=%sqrt(N):N=!vec[2]!%"  %== sqrt(N) applied ==%
%normalize% vec  %== normalize macro applied ==%
%dot% light vec dot_out  %== dot macro applied ==%
rem since both light and vec are normalized to 100,
rem then dot_out is scaled up by 100*100 now.
set /a "dot_out/=100"  %== scale-down to 100*[actual] to prevent overflow before exponentiation ==%
set "scaleup=1"  %== after exponentiation, b would be scaleup*[actual] ==%
set "b=1"
for /l %%? in (1,1,%k%) do set /a "b*=dot_out","scaleup*=100" %== exponentiation ==%
set /a "b+=ambient*scaleup/10"  %== add ambient/10 to b ==%
set /a "b/=scaleup/100"  %== scale-down to 100*[actual] ==%
set /a "intensity/=100"  %== final scale-down ==%
if !intensity! lss 0 set "intensity=0"
for %%c in (!intensity!) do set "line=!line!!shades[%%c]!"
) else (
set "line=!line! "
)
)
echo(!line!
)
goto :EOF
Output:
                               eeeeeeeeee&&&&&##
eoooo*****ooooooooeeeee&&&&###%
oo******!!!!!********oooooeeee&&&&###%%
o**!!!!!!!!!!!!!!!!!!*****oooooeeee&&&&###%%%
o**!!!!:::::::::::!!!!!!!!!****oooooeee&&&&&###%%%%
o*!!!:::::::::::::::::::!!!!!!*****ooooeeee&&&&####%%%%
o*!!!:::::........:::::::::!!!!!!*****oooeeee&&&&&####%%%%@
o*!!!::::.............::::::::!!!!!!****ooooeeee&&&&####%%%%%@@
**!!::::.................::::::!!!!!!*****ooooeeee&&&&####%%%%%%@
e*!!!::::..................:::::::!!!!!!****ooooeeee&&&&#####%%%%%@@@
o*!!!:::....................::::::!!!!!!!****ooooeeee&&&&&####%%%%%%@@@
e**!!::::....................::::::!!!!!!*****ooooeeee&&&&#####%%%%%%@@@@
e**!!!::::..................::::::::!!!!!!****ooooeeeee&&&&#####%%%%%%%@@@@
o**!!:::::..................:::::::!!!!!!*****ooooeeeee&&&&#####%%%%%%%@@@@
eo*!!!::::::...............::::::::!!!!!!*****ooooeeeee&&&&&#####%%%%%%%@@@@@
o**!!!!:::::::.........::::::::::!!!!!!!*****oooooeeee&&&&&&####%%%%%%%%@@@@@
eo**!!!!!:::::::::::::::::::::::!!!!!!!!*****oooooeeeee&&&&&#####%%%%%%%%@@@@@@
eoo**!!!!!::::::::::::::::::::!!!!!!!!******oooooeeeee&&&&&######%%%%%%%@@@@@@@
eoo***!!!!!:::::::::::::::::!!!!!!!!*******ooooeeeeee&&&&&######%%%%%%%%@@@@@@@
eoo****!!!!!!!!!!:::!:!!!!!!!!!!!!*******oooooeeeeee&&&&&######%%%%%%%%@@@@@@@@
eeoo****!!!!!!!!!!!!!!!!!!!!!!!!********oooooeeeeee&&&&&&#####%%%%%%%%%@@@@@@@@
&eeoo******!!!!!!!!!!!!!!!!!*********ooooooeeeeee&&&&&&######%%%%%%%%%@@@@@@@@@
&eeeooo********!*!!!!!************oooooooeeeeeee&&&&&&######%%%%%%%%%@@@@@@@@@@
#&eeeooooo********************ooooooooeeeeeeee&&&&&&#######%%%%%%%%%@@@@@@@@@@@
&&eeeeoooooooo*********oooooooooooeeeeeeee&&&&&&&&######%%%%%%%%%%@@@@@@@@@@@
#&&&eeeeeooooooooooooooooooooooeeeeeeeee&&&&&&&&#######%%%%%%%%%%@@@@@@@@@@@@
#&&&&eeeeeeeeoooooooooeeeeeeeeeeeeee&&&&&&&&########%%%%%%%%%%@@@@@@@@@@@@@
%##&&&&&eeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&&########%%%%%%%%%%%@@@@@@@@@@@@@@
%###&&&&&&&&eeeeeeeeeeeee&&&&&&&&&&&&&########%%%%%%%%%%%%@@@@@@@@@@@@@@@
%%####&&&&&&&&&&&&&&&&&&&&&&&&&&###########%%%%%%%%%%%%%@@@@@@@@@@@@@@@
%%%#######&&&&&&&&&&&&&&&&#############%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@
%%%##############################%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@
%%%%%%%####################%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@
@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@
@@%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@

## Befunge

Translation of: C

While based on the C implementation, the algorithm has been considerably simplified to try and avoid floating point (which Befunge doesn't support) and minimise the need for sqrt calculations (which we approximate using the Babylonian method).

The first four values on the stack define the radius (45* = 20) and the light vector (65*65*"2" = 30;30;50). The k parameter has been hardcoded to 2, and the ambient light is approximated by adjusting the shade characters (defined on the last line).

Also note that the z-coordinate of the light vector is negated at runtime to more closely match the C defaults. This is preferable to making the initial constant negative since negative data values aren't supported across all Befunge implementations.

45*65*65*"2"30p20p10p::00p2*40p4*5vv<
>60p140g->:::*00g50g*60g40g-:*-\-v0>1
^_@#\g0<|\g04:+1, <*84_v#\0:<>p^
>v>g2+:5^$>g:*++*/7g^>*:9$#<"~"/:"~"v
g:^06,+55<^03*<v09p07%"~"p09/"~"p08%<
^>#0 *#12#<0g:^>+::"~~"90g*80g+*70gv|
g-10g*+:9**00gv|!*\2\-20::/2-\/\+<>
%#&eo*!:..^g05<>$030g-*9/\20g*+60g40^  Output:  eeeeeeeeeee&&&&&# eooo********oooooooeeee&&&&###% oo****!!!!!!!!********ooooeeeee&&&###%% o**!!!!!!!!!!!!!!!!!!!*****oooooeeee&&&####%% o*!!!!:::::::::::::::!!!!!!*****ooooeeee&&&&####%%% **!!:::::::....::::::::::!!!!!!****ooooeeeee&&&####%%%% **!!::::.............::::::::!!!!!****ooooeeee&&&&####%%%%% o*!!::::.................::::::!!!!!!****ooooeeee&&&&####%%%%%% *!!::::....................::::::!!!!!****ooooeeeee&&&&####%%%%%% e*!!:::......................::::::!!!!!*****ooooeeee&&&&####%%%%%%%% o*!!:::.......................::::::!!!!!*****ooooeeee&&&&#####%%%%%%%% o*!!::::.......................::::::!!!!!****oooooeeee&&&&#####%%%%%%%%% e**!!:::.......................::::::!!!!!*****ooooeeeee&&&&#####%%%%%%%%%% o*!!!:::......................:::::::!!!!!*****ooooeeeee&&&&#####%%%%%%%%%% o**!!!::::...................::::::::!!!!!*****oooooeeee&&&&&#####%%%%%%%%%%% o**!!!:::::................::::::::!!!!!!*****oooooeeeee&&&&#####%%%%%%%%%%%% eo**!!!:::::::............:::::::::!!!!!!*****oooooeeeee&&&&&#####%%%%%%%%%%%%% eo***!!!:::::::::::::::::::::::::!!!!!!******oooooeeeee&&&&&#####%%%%%%%%%%%%%% eoo**!!!!!::::::::::::::::::::!!!!!!!!******oooooeeeee&&&&&######%%%%%%%%%%%%%% eoo***!!!!!!:::::::::::::::!!!!!!!!!******ooooooeeeee&&&&&######%%%%%%%%%%%%%%% eeoo****!!!!!!!!!!!!!!!!!!!!!!!!!*******ooooooeeeeee&&&&&######%%%%%%%%%%%%%%%% &eooo*****!!!!!!!!!!!!!!!!!!!!********ooooooeeeeee&&&&&&######%%%%%%%%%%%%%%%%% &eeoooo*******!!!!!!!!!!***********oooooooeeeeeee&&&&&&######%%%%%%%%%%%%%%%%%# &&eeeoooo***********************ooooooooeeeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%# &&eeeooooooo**************ooooooooooeeeeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%# #&&eeeeeoooooooooooooooooooooooooeeeeeeee&&&&&&&########%%%%%%%%%%%%%%%%%%%## #&&&eeeeeeeooooooooooooooooeeeeeeeeee&&&&&&&&########%%%%%%%%%%%%%%%%%%%%## %##&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&&########%%%%%%%%%%%%%%%%%%%%%##& %###&&&&&&eeeeeeeeeeeeeeeeee&&&&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%##& %####&&&&&&&&&&&&&&&&&&&&&&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%##& %%######&&&&&&&&&&&&&&&&&&&&############%%%%%%%%%%%%%%%%%%%%%%%%%%##e %%%################################%%%%%%%%%%%%%%%%%%%%%%%%%%%##& %%%%%########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%###& %%%%%%%%%###########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%###& %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%###& %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##&& %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%###& %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%####& %%%%%%%%%%%%%%%%%%%%%%%%%%####& %%%%%%%%%%%%#####  ## Brlcad opendb balls.g y # Create a database to hold our shapes units cm # Set the unit of measure in ball.s sph 0 0 0 3 # Create a sphere of radius 3 cm named ball.s with its centre at 0,0,0 ## C The lighting calculation is somewhere between crude and bogus, but hey, I'm shading it with ASCII characters, don't expect too much. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <math.h> const char *shades = ".:!*oe&#%@"; double light[3] = { 30, 30, -50 }; void normalize(double * v) { double len = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); v[0] /= len; v[1] /= len; v[2] /= len; } double dot(double *x, double *y) { double d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2]; return d < 0 ? -d : 0; } void draw_sphere(double R, double k, double ambient) { int i, j, intensity; double b; double vec[3], x, y; for (i = floor(-R); i <= ceil(R); i++) { x = i + .5; for (j = floor(-2 * R); j <= ceil(2 * R); j++) { y = j / 2. + .5; if (x * x + y * y <= R * R) { vec[0] = x; vec[1] = y; vec[2] = sqrt(R * R - x * x - y * y); normalize(vec); b = pow(dot(light, vec), k) + ambient; intensity = (1 - b) * (sizeof(shades) - 1); if (intensity < 0) intensity = 0; if (intensity >= sizeof(shades) - 1) intensity = sizeof(shades) - 2; putchar(shades[intensity]); } else putchar(' '); } putchar('\n'); } } int main() { normalize(light); draw_sphere(20, 4, .1); draw_sphere(10, 2, .4); return 0; }  Output:  #############%%%% ##&&eeeeeeeeee&&&&&&&####%%%%%%%% &&eeooooooooooooooeeeee&&&&######%%%%%%%% eeoo**************oooooooeeee&&&&####%%%%%%%% &&oo**!!!!!!::!!!!!!!!****oooooee&&&&######%%%%%%%%%% eeoo!!!!::::::::::::::!!!!*****ooeeee&&&&####%%%%%%%%%%%% ee**!!::::............::::!!!!***ooooeeee&&######%%%%%%%%%%%% &&oo!!::..................::!!!!*****ooeeee&&&&####%%%%%%%%%%%%%% oo!!::....................::::!!*****ooeeee&&&&####%%%%%%%%%%%%%% ee**!!::....................::::!!*****ooeeee&&&&####%%%%%%%%%%%%%%%% &&oo!!::......................::::!!*****ooeeee&&&&######%%%%%%%%%%%%%%%% ee**!!::......................::::!!*****ooeeee&&&&######%%%%%%%%%%%%%%%% ##oo**!!::......................::!!!!*****ooeeee&&&&####%%%%%%%%%%%%%%%%%%%% &&oo**::::....................::::!!!!***ooooeeee&&&&####%%%%%%%%%%%%%%%%%%%% eeoo**!!::..................::::!!!!*****ooooee&&&&######%%%%%%%%%%%%%%%%%%%% eeoo**!!::................::::!!!!****oooooeeee&&&&######%%%%%%%%%%%%%%%%%%%% #eeoo**!!::::............::::!!!!!!****oooeeee&&&&&&######%%%%%%%%%%%%%%%%%%%%%% #eeoo**!!!!::::::::::::::::!!!!!!****oooooeeee&&&&######%%%%%%%%%%%%%%%%%%%%%%%% #eeoooo**!!!!!!::::::::!!!!!!******ooooeeeee&&&&&&######%%%%%%%%%%%%%%%%%%%%%%%% #&&eeoo****!!!!!!!!!!!!!!!!******ooooeeeee&&&&&&######%%%%%%%%%%%%%%%%%%%%%%%%%% #&&eeoooo********************ooooooeeee&&&&&&&######%%%%%%%%%%%%%%%%%%%%%%%%%%%% #&&&&eeoooooo************ooooooeeeeee&&&&&&&########%%%%%%%%%%%%%%%%%%%%%%%%%%%% %##&&eeeeeeooooooooooooooooooeeeeee&&&&&&&########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %####&&&&eeeeeeeeeeeeeeeeeeeeee&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%##&&&&&&eeeeeeeeeeeeeeee&&&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%######&&&&&&&&&&&&&&&&&&&&&&&&###########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%########&&&&&&&&&&&&&&############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%##############################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%######################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%####%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%% ::..:::::!!** .............::!!**oo ...................::!!**ooee .......................::!!ooeeee .......................::!!**ooee .........................::!!**ooeeee .........................::!!**ooeeee :.........................::!!**ooeeeeee ........................::!!**ooooeeeeee :.......................::!!**ooeeeeeeee :.....................::!!****ooeeeeeeee !::................:::!!****ooeeeeeeeeee *!!::..........::::!!!****ooooeeeeeeeeee **!!::::::::::!!!!*****ooooeeeeeeeeee oo**!!!!!!!!!!*******ooooeeeeeeeeeeee oooo********oooooooeeeeeeeeeeeeee eeeeooooooooooeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeee  ### Fun with 3D noise texture #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAXD 8 int g[] = { -1, 1, -1, 1 }; /* Perlin-like noise */ static inline void hashed(int *data, int *out, int len) { # define ror(a, d) ((a << (d)) | (a >> (32 - d))) register unsigned int h = 0x12345678, tmp; unsigned int *d = (void*)data; int i = len; while (i--) { tmp = *d++; h += ror(h, 15) ^ ror(tmp, 5); } h ^= ror(h, 7); h += ror(h, 23); h ^= ror(h, 19); h += ror(h, 11); h ^= ror(h, 13); h += ror(h, 17); # undef ror for (i = len; i--; ) { out[i] = g[h & 3]; h >>= 2; } } double scale[MAXD], scale_u[MAXD]; void noise_init() { int i; for (i = 1; i < MAXD; i++) { scale[i] = 1 / (1 + sqrt(i + 1)); scale_u[i] = scale[i] / sqrt(i + 1); } } double noise(double *x, int d) { # define sum(s, x) for (s = 0, j = 0; j < d; j++) s += x register int i, j; int n[MAXD], o[MAXD], g[MAXD], tmp; double s, r, t, w, ret, u[MAXD]; sum(s, x[j]); s *= scale[d]; for (i = 0; i < d; i++) { o[i] = i; t = x[i] + s; u[i] = t - (n[i] = floor(t)); } o[d] = 0; for (i = 0; i < d - 1; i++) for (j = i; j < d; j++) if (u[o[i]] < u[o[j]]) tmp = o[i], o[i] = o[j], o[j] = tmp; ret = w = 0, r = 1; for (s = 0, j = 0; j < d; j++) s += n[j]; s *= scale_u[d]; for (i = 0; i <= d; i++) { for (j = 0; j < d; j++) u[j] = x[j] + s - n[j]; for (t = (d + 1.) / (2 * d), j = 0; j < d; j++) { t -= u[j] * u[j]; if (t <= 0) break; } if (t >= 0) { r = 0; hashed(n, g, d); for (j = 0; j < d; j++) if (g[j]) r += (g[j] == 1 ? u[j] : -u[j]); t *= t; ret += r * t * t; } if (i < d) { n[o[i]]++; s += scale_u[d]; } } return ret * (d * d); } double get_noise2(double x, double y) { int i, ws; double r = 0, v[2]; for (i = 1, ws = 0; i <= 128; i <<= 1) { v[0] = x * i, v[1] = y * i; r += noise(v, 2); ws ++; } r /= ws; return r; } double get_noise3(double x, double y, double z) { int i, ws; double r = 0, v[3], w; for (i = 1, ws = 0; i <= 32; i <<= 1) { v[0] = x * i, v[1] = y * i, v[2] = z * i; w = 1./sqrt(i); r += noise(v, 3) * w; ws += w; } return r / ws; } int main(int c, char** v) { unsigned char pix[256 * 256], *p; int i, j; double x, y, z, w; FILE *fp; noise_init(); for (p = pix, i = 0; i < 256 * 256; i++) *p++ = 0; for (p = pix, i = 0; i < 256; i++) { y = (i - 128) / 125.; for (j = 0; j < 256; j++, p++) { x = (j - 128) / 125.; *p = (get_noise2(i/256., j/256.) + 1) / 6 * i; z = 1- x*x - y*y; if (z < 0) continue; z = sqrt(z); w = get_noise3(x, y, z); w = (w + 1) / 2; w *= (1 + x - y + z) / 3.5; if (w < 0) w = 0; *p = w * 255; } } fp = fopen("out.pgm", "w+"); fprintf(fp, "P5\n256 256\n255\n"); fwrite(pix, 1, 256 * 256, fp); fclose(fp); return 0; }  ## C# Translation of: C using System; namespace Sphere { internal class Program { private const string Shades = ".:!*oe%&#@"; private static readonly double[] Light = {30, 30, -50}; private static void Normalize(double[] v) { double len = Math.Sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); v[0] /= len; v[1] /= len; v[2] /= len; } private static double Dot(double[] x, double[] y) { double d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2]; return d < 0 ? -d : 0; } public static void DrawSphere(double r, double k, double ambient) { var vec = new double[3]; for(var i = (int)Math.Floor(-r); i <= (int)Math.Ceiling(r); i++) { double x = i + .5; for(var j = (int)Math.Floor(-2*r); j <= (int)Math.Ceiling(2*r); j++) { double y = j/2.0 + .5; if(x*x + y*y <= r*r) { vec[0] = x; vec[1] = y; vec[2] = Math.Sqrt(r*r - x*x - y*y); Normalize(vec); double b = Math.Pow(Dot(Light, vec), k) + ambient; int intensity = (b <= 0) ? Shades.Length - 2 : (int)Math.Max((1 - b)*(Shades.Length - 1), 0); Console.Write(Shades[intensity]); } else Console.Write(' '); } Console.WriteLine(); } } private static void Main() { Normalize(Light); DrawSphere(6, 4, .1); DrawSphere(10, 2, .4); Console.ReadKey(); } } }  ## C++ Library: Qt // Based on https://www.cairographics.org/samples/gradient/ #include <QImage> #include <QPainter> int main() { const QColor black(0, 0, 0); const QColor white(255, 255, 255); const int size = 300; const double diameter = 0.6 * size; QImage image(size, size, QImage::Format_RGB32); QPainter painter(&image); painter.setRenderHint(QPainter::Antialiasing); QLinearGradient linearGradient(0, 0, 0, size); linearGradient.setColorAt(0, white); linearGradient.setColorAt(1, black); QBrush brush(linearGradient); painter.fillRect(QRect(0, 0, size, size), brush); QPointF point1(0.4 * size, 0.4 * size); QPointF point2(0.45 * size, 0.4 * size); QRadialGradient radialGradient(point1, size * 0.5, point2, size * 0.1); radialGradient.setColorAt(0, white); radialGradient.setColorAt(1, black); QBrush brush2(radialGradient); painter.setPen(Qt::NoPen); painter.setBrush(brush2); painter.drawEllipse(QRectF((size - diameter)/2, (size - diameter)/2, diameter, diameter)); image.save("sphere.png"); return 0; }  Output: ## Clojure Library: quil (use 'quil.core) (def w 500) (def h 400) (defn setup [] (background 0)) (defn draw [] (push-matrix) (translate 250 200 0) (sphere 100) (pop-matrix)) (defsketch main :title "sphere" :setup setup :size [w h] :draw draw :renderer :opengl)  Output: ## Common Lisp Library: cl-cairo2 Saved as a png file and rendered in a X-Window. Unfortunately the file upload isn't working anymore for like four years so I cannot show my results directly. ;; * Loading the cairo bindings (eval-when (:compile-toplevel :load-toplevel) (ql:quickload '("cl-cairo2" "cl-cairo2-xlib"))) ;; * The package definition (defpackage :sphere (:use :common-lisp :cl-cairo2)) (in-package :sphere) (defparameter *context* nil) (defparameter *size* 400) (defparameter *middle* (/ *size* 2)) ;; Opening a display and draw a sphere (let ((width *size*) (height *size*)) ;; Draw to a X-Window (setf *context* (create-xlib-image-context width height :window-name "Sphere")) ;; Clear the whole canvas with gray (rectangle 0 0 width height) (set-source-rgb 127 127 127) (fill-path) ;; Draw a the sphere as circa with a radial pattern (with-patterns ((pat (create-radial-pattern (* 0.9 *middle*) (* 0.8 *middle*) (* 0.2 *middle*) (* 0.8 *middle*) (* 0.8 *middle*) *middle*))) (pattern-add-color-stop-rgba pat 0 1 1 1 1) (pattern-add-color-stop-rgba pat 1 0 0 0 1) (set-source pat) (arc *middle* *middle* 180 0 (* 2 pi)) (fill-path)) ;; Draw to a png file (with-png-file ("sphere.png" :rgb24 width height) ;; Clear the whole canvas with gray (rectangle 0 0 width height) (set-source-rgb 127 127 127) (fill-path) ;; Draw a the sphere as circa with a radial pattern (with-patterns ((pat (create-radial-pattern (* 0.9 *middle*) (* 0.8 *middle*) (* 0.2 *middle*) (* 0.8 *middle*) (* 0.8 *middle*) *middle*))) (pattern-add-color-stop-rgba pat 0 1 1 1 1) (pattern-add-color-stop-rgba pat 1 0 0 0 1) (set-source pat) (arc *middle* *middle* 180 0 (* 2 pi)) (fill-path))))  ## ContextFree startshape SPHERE shape SPHERE { CIRCLE[] SPHERE[x 0.1% y 0.1%s 0.99 0.99 b 0.05] } ## Craft Basic let j = 2 for i = 221 to 0 step j * -1 for k = -3.14 to 3.14 step .01 dot 221 + i * sin(k), 222 + 221 * cos(k) dot 221 + 221 * sin(k), 222 + (i - 1) * cos(k) wait next k let j = j + 1 next i  ## D Translation of: C import std.stdio, std.math, std.algorithm, std.numeric; alias V3 = double[3]; immutable light = normalize([30.0, 30.0, -50.0]); V3 normalize(V3 v) pure @nogc { v[] /= dotProduct(v, v) ^^ 0.5; return v; } double dot(in ref V3 x, in ref V3 y) pure nothrow @nogc { immutable double d = dotProduct(x, y); return d < 0 ? -d : 0; } void drawSphere(in double R, in double k, in double ambient) @nogc { enum shades = ".:!*oe&#%@"; foreach (immutable i; cast(int)floor(-R) .. cast(int)ceil(R) + 1) { immutable double x = i + 0.5; foreach (immutable j; cast(int)floor(-2 * R) .. cast(int)ceil(2 * R) + 1) { immutable double y = j / 2. + 0.5; if (x ^^ 2 + y ^^ 2 <= R ^^ 2) { immutable vec = [x, y, (R^^2 - x^^2 - y^^2) ^^ 0.5] .normalize; immutable double b = dot(light, vec) ^^ k + ambient; int intensity = cast(int)((1 - b) * (shades.length-1)); intensity = min(shades.length - 1, max(intensity, 0)); shades[intensity].putchar; } else ' '.putchar; } '\n'.putchar; } } void main() { drawSphere(20, 4, 0.1); drawSphere(10, 2, 0.4); }  ## Delphi Translation of: C Under Microsoft Windows: If you notice the big sphere loses its roundness, then try increasing the width of the Windows console. By default it’s 80; so put it to something bigger, let’s say 90. Steps: Run the CMD Windows shell. Then follow this path to setup the new width: Main Menu-> Properties -> Layout -> Window Size -> Width. program DrawASphere; {$APPTYPE CONSOLE}

uses
SysUtils,
Math;

type
TDouble3  = array[0..2] of Double;
TChar10 = array[0..9] of Char;

var
shades: TChar10 = ('.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@');
light: TDouble3 = (30, 30, -50 );

procedure normalize(var v: TDouble3);
var
len: Double;
begin
len:= sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] := v[0] / len;
v[1] := v[1] / len;
v[2] := v[2] / len;
end;

function dot(x, y: TDouble3): Double;
begin
Result:= x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
Result:= IfThen(Result < 0, -Result, 0 );
end;

procedure drawSphere(R, k, ambient: Double);
var
vec: TDouble3;
x, y, b: Double;
i, j,
intensity: Integer;
begin
for i:= Floor(-R) to Ceil(R) do
begin
x := i + 0.5;
for j:= Floor(-2*R) to Ceil(2 * R) do
begin
y:= j / 2 + 0.5;
if(x * x + y * y <= R * R) then
begin
vec[0]:= x;
vec[1]:= y;
vec[2]:= sqrt(R * R - x * x - y * y);
normalize(vec);
b:= Power(dot(light, vec), k) + ambient;
intensity:= IfThen(b <= 0,
Trunc(max( (1 - b) * (Length(shades) - 1), 0 )));
end
else
Write(' ');
end;
Writeln;
end;
end;

begin
normalize(light);
drawSphere(19, 4, 0.1);
drawSphere(10, 2, 0.4);
end.

Output:
                             &&&&&&&&&&#######
&eeeeeooeeeeeeee&&&&&&#######
eeooo*********oooooeeeee&&&&&#######%
eo***!!!!!!!!!!!*****ooooeeee&&&&&#######%%
eo**!!!::::::::::!!!!!****ooooeeee&&&&########%%%
eo*!!::::........:::::!!!!****oooeeee&&&&########%%%%
eo*!!::..............:::::!!!***ooooeeee&&&&#########%%%%
eo*!!::..................:::!!!!***oooeeee&&&&&########%%%%%%
eo*!::....................::::!!!***ooooeeee&&&&#########%%%%%%
o**!::.....................::::!!!***ooooeeee&&&&#########%%%%%%%
eo*!::......................::::!!!***ooooeeee&&&&##########%%%%%%%
eo*!!::......................:::!!!!***ooooeee&&&&&##########%%%%%%%%
eo**!!::.....................:::!!!!***ooooeeee&&&&&##########%%%%%%%%%
&eo**!!::...................::::!!!!****oooeeeee&&&&&##########%%%%%%%%%%
eeo**!!:::................:::::!!!!****ooooeeee&&&&&##########%%%%%%%%%%%
&eoo**!!!::::............:::::!!!!****oooooeeee&&&&&###########%%%%%%%%%%%%
&eeo***!!!::::::::::::::::::!!!!!****ooooeeeee&&&&&&##########%%%%%%%%%%%%%
&eeoo***!!!!::::::::::::!!!!!!*****oooooeeeee&&&&&&###########%%%%%%%%%%%%%
&&eeoo****!!!!!!!!!!!!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%%
&&eeeooo*****!!!!!!!!!!*******ooooooeeeeee&&&&&&############%%%%%%%%%%%%%%%
#&&eeeoooo*****************oooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%%
#&&&eeeeoooooooooooooooooooooooeeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%%
##&&&&eeeeeoooooooooooooooeeeeeeeee&&&&&&&&##############%%%%%%%%%%%%%%%%%%
###&&&&eeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%
####&&&&&&&eeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%
#####&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%
########&&&&&&&&&&&&&&&&&&&####################%%%%%%%%%%%%%%%%%%%%%%
############################################%%%%%%%%%%%%%%%%%%%%%%%
%#######################################%%%%%%%%%%%%%%%%%%%%%%%%%
%%##################################%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%###########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%#################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%

::...:::!!!*o
..............::!!*oo
..................::!!**ooe
.....................::!!**ooee
.......................::!!**ooee
........................::!!**oooee
.........................::!!**oooeee
:........................::!!!**oooeeee
........................::!!!**ooooeeee
:......................::!!!***oooeeeee
:....................:::!!!***oooeeeeee
!:.................:::!!!****oooeeeeeee
*!:::...........::::!!!!***ooooeeeeeeee
*!!!:::::::::::!!!!!****oooooeeeeeeee
o**!!!!!!!!!!!!!*****oooooeeeeeeeee
oo**************ooooooeeeeeeeeeee
eoooooooooooooooooeeeeeeeeeeeee
eeeooooooooeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeee


## DWScript

Translation of: C

but adapted to spit out a PGM image

type
TFloat3  = array[0..2] of Float;

var
light : TFloat3 = [ 30, 30, -50 ];

procedure normalize(var v : TFloat3);
var
len: Float;
begin
len := sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] /= len;
v[1] /= len;
v[2] /= len;
end;

function dot(x, y : TFloat3) : Float;
begin
Result := x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
if Result<0 then
Result:=-Result
else Result:=0;
end;

procedure drawSphere(R, k, ambient : Float);
var
vec : TFloat3;
x, y, b : Float;
i, j, size, intensity : Integer;
begin
size:=Trunc(Ceil(R)-Floor(-R)+1);
PrintLn('P2');
PrintLn(IntToStr(size)+' '+IntToStr(size));
PrintLn('255');
for i := Floor(-R) to Ceil(R) do begin
x := i + 0.5;
for j := Floor(-R) to Ceil(R) do begin
y := j + 0.5;
if (x * x + y * y <= R * R) then begin
vec[0] := x;
vec[1] := y;
vec[2] := sqrt(R * R - x * x - y * y);
normalize(vec);
b := Power(dot(light, vec), k) + ambient;
intensity := ClampInt( Round(b*255), 0, 255);
Print(intensity);
Print(' ')
end else Print('0 ');
end;
PrintLn('');
end;
end;

normalize(light);
drawSphere(19, 4, 0.1);


## Emacs Lisp

Translation of: Go
; Draw a sphere

(defun normalize (v)
"Normalize a vector."
(setq invlen (/ 1.0 (sqrt (dot v v))))
(mapcar (lambda (x) (* invlen x)) v))

(defun dot (v1 v2)
"Dot product of two vectors."
(+ (* (car v1) (car v2))

(defun make-array (size)
"Create an empty array with size*size elements."
(setq m-array (make-vector size nil))
(dotimes (i size)
(setf (aref m-array i) (make-vector size 0)))
m-array)

(defun pic-lines (arr size)
"Turn array into a string."
(setq all "")
(dotimes (y size)
(setq line "")
(dotimes (x size)
(setq line (concat line (format "%i \n" (elt (elt arr y) x)))))
(setq all (concat all line "\n")))
all)

(defun pic-show (arr size)
"Convert size*size array to grayscale PBM image and show it."
(insert-image (create-image (concat (format "P2
%i %i 255\n" size size) (pic-lines arr size)) 'pbm t)))

(defun sphere (size k amb dir)
"Draw a sphere."
(let ((arr (make-array size))
(ndir (normalize dir))
(r (/ size 2)))
(dotimes (yp size)
(dotimes (xp size)
(setq x (- xp r))
(setq y (- yp r))
(setq z (- (* r r) (* x x) (* y y)))
(if (>= z 0)
(let* ((vec (normalize (list x y (sqrt z))))
(s (max 0 (dot vec ndir)))
(lum (max 0 (min 255 (* 255 (+ amb (expt s k))
(/ (1+ amb)))))))
(setf (elt (elt arr yp) xp) lum)))))
(pic-show arr size)))

(sphere 200 1.5 0.2 '(-30 -30 50))


## ERRE

Using ASCII art: output is written to 'SPHERE.PRN' sequential file.

PROGRAM SPHERE

CONST SHADES$=".:!*oe&#%@" DIM LIGHT[2],X[2],Y[2],V[2],VEC[2] PROCEDURE DOT(X[],Y[]->D) D=X[0]*Y[0]+X[1]*Y[1]+X[2]*Y[2] IF D<0 THEN D=-D ELSE D=0 END IF END PROCEDURE PROCEDURE NORMALIZE(V[]->V[]) LUNG=SQR(V[0]*V[0]+V[1]*V[1]+V[2]*V[2]) V[0]=V[0]/LUNG V[1]=V[1]/LUNG V[2]=V[2]/LUNG END PROCEDURE PROCEDURE PDRAW(R,K,AMBIENT) FOR I=INT(-R) TO INT(R) DO X=I+0.5 FOR J=INT(-2*R) TO INT(2*R) DO Y=J/2+0.5 IF (X*X+Y*Y<=R*R) THEN VEC[0]=X VEC[1]=Y VEC[2]=SQR(R*R-X*X-Y*Y) NORMALIZE(VEC[]->VEC[]) DOT(LIGHT[],VEC[]->D) B=D^K+AMBIENT INTENSITY%=(1-B)*(LEN(SHADES$)-1)
IF (INTENSITY%<0) THEN INTENSITY%=0 END IF
IF (INTENSITY%>=LEN(SHADES$)-1) THEN INTENSITY%=LEN(SHADES$)-2
END IF
PRINT(#1,MID$(SHADES$,INTENSITY%+1,1);)
ELSE
PRINT(#1,(" ");)
END IF
END FOR
PRINT(#1,)
END FOR
END PROCEDURE

BEGIN
LIGHT[]=(30,30,-50)
OPEN("O",1,"SPHERE.PRN")
NORMALIZE(LIGHT[]->LIGHT[])
PDRAW(10,2,0.4)

PRINT(#1,STRING$(79,"=")) PDRAW(20,4,0.1) CLOSE(1) END PROGRAM Output:  !::::::!!!**o ............:::!!**oe :................::!!**ooee :...................::!!**ooeee ......................::!!**ooeee .......................::!!**ooeeee .......................:::!!**ooeeeee :.......................::!!***ooeeeeee :......................::!!!**oooeeeeee :....................:::!!!**oooeeeeeee !:..................:::!!***oooeeeeeeee !!:..............::::!!!***oooeeeeeeeee *!!::::.....::::::!!!!***ooooeeeeeeeeee o*!!!!::::::!!!!!!****ooooeeeeeeeeeee o****!!!!!!!******oooooeeeeeeeeeeee eooo********oooooooeeeeeeeeeeeeee eeeoooooooooooeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeee =============================================================================== ##############%%% #&&eeeeeeeeeee&&&&&&######%%%%% &eeeoooooooooooooeeeee&&&&&######%%%%%% &eooo**************oooooeeee&&&&&#####%%%%%%% &eoo**!!!!!!!!!!!!!!*****ooooeeee&&&&######%%%%%%%% eoo**!!!::::::::::::!!!!****ooooeeee&&&&######%%%%%%%%% eoo*!!!::::.......::::::!!!!****oooeeee&&&&######%%%%%%%%%% &eo*!!:::..............::::!!!!***ooooeeee&&&&######%%%%%%%%%%% eo**!!::.................::::!!!****oooeeee&&&&######%%%%%%%%%%%% &eo*!!:::..................::::!!!!***oooeeee&&&&&######%%%%%%%%%%%%% &eo*!!:::...................::::!!!!***oooeeee&&&&&######%%%%%%%%%%%%%% &eo**!!::....................::::!!!****oooeeee&&&&&######%%%%%%%%%%%%%%% #eoo*!!:::...................::::!!!!***ooooeeee&&&&#######%%%%%%%%%%%%%%%% &eo**!!:::.................:::::!!!!****oooeeee&&&&&#######%%%%%%%%%%%%%%%% &eoo**!!::::...............:::::!!!!****ooooeeee&&&&#######%%%%%%%%%%%%%%%%%% &eoo**!!!::::...........::::::!!!!*****ooooeeee&&&&&#######%%%%%%%%%%%%%%%%%% #&eoo***!!!::::::::::::::::::!!!!!****ooooeeeee&&&&&#######%%%%%%%%%%%%%%%%%%%% #&eeoo***!!!!::::::::::::!!!!!!!*****ooooeeeee&&&&&#######%%%%%%%%%%%%%%%%%%%%% #&eeooo****!!!!!!!!!!!!!!!!!!******ooooeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%%%% #&&eeooo******!!!!!!!!!!!*******ooooooeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%%%%% #&&&eeooooo******************ooooooeeeeee&&&&&&########%%%%%%%%%%%%%%%%%%%%%%%% ##&&&eeeooooooo********oooooooooeeeeeee&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%% ###&&&eeeeeooooooooooooooooooeeeeeee&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%%% %###&&&&eeeeeeeeeeeoeeeeeeeeeeeee&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%%%% %####&&&&&eeeeeeeeeeeeeeeeee&&&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%#####&&&&&&&&&&&&&&&&&&&&&&&&&&&############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%#######&&&&&&&&&&&&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%############&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%##############################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%#######################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%#########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%  ## Evaldraw Draw a sphere. We dont need to wrap the main () function with braces if we have no functions. () cls(0); clz(1e32); setcam(0,0,-5,0,0); setcol(128,64,64); drawsph(0,0,0,1);  ## Factor Library: raylib Works with: Factor version 0.99 2020-03-02 USING: classes.struct kernel raylib.ffi ; 640 480 "sphere" init-window S{ Camera3D { position S{ Vector3 f 4.5 4.5 4.5 } } { target S{ Vector3 f 0 0 0 } } { up S{ Vector3 f 0 1 0 } } { fovy 45.0 } { type 0 } } 60 set-target-fps [ window-should-close ] [ begin-drawing BLACK clear-background dup begin-mode-3d S{ Vector3 f 0 0 0 } 2 20 20 LIME draw-sphere-wires end-mode-3d end-drawing ] until drop close-window  Output: ## Forth Works with: gforth version 0.7.3 Inspired by C version but simplified. Traditionaly, Forth use Fixed-Point Arithmetic (here with a 1000 scale). Integer square root function is hand coded. ### ASCII output : 3dup 2 pick 2 pick 2 pick ; : sqrt ( u -- sqrt ) ( Babylonian method ) dup 2/ ( first square root guess is half ) dup 0= if drop exit then ( sqrt[0]=0, sqrt[1]=1 ) begin dup >r 2dup / r> + 2/ ( stack: square old-guess new-guess ) 2dup > while ( as long as guess is decreasing ) nip repeat ( forget old-guess and repeat ) drop nip ; : normalize ( x1 y1 z1 -- x1' y1' z1' ) ( normalise down to 1000 ) 3dup dup * rot dup * rot dup * + + sqrt 1000 / >r ( length ) r@ / rot r@ / rot r> / rot ; : r2-y2-x2 ( x y r -- z2 ) dup * swap dup * - swap dup * - ; : shade ( u -- c ) C" @#&eo%*!:. " + c@ ; : map-to-shade ( u -- u ) 0 shade * 1000 / 1 max 0 shade min ; : dot-light ( x y z -- i ) ( hard coded light vector z, y, x ) -770 * rot 461 * rot 461 * + + 0 min 1000 / ; : intensity ( x y z -- u ) dot-light dup * 1000 / map-to-shade ; : pixel ( x y r -- c ) 3dup r2-y2-x2 dup 0> if ( if in disk ) sqrt nip normalize intensity shade ( z=sqrt[r2-x2-y2] ) else 2drop 2drop bl ( else blank ) then ; : draw ( r -- ) ( r x1000 ) 1000 * dup dup negate do cr dup dup negate do dup I 500 + J 500 + rot pixel emit 500 +loop 1000 +loop drop ; 20 draw 10 draw  Output:  eeooooeeeeee&&&## o%%%%******%%%%%%ooooeee&&&##@@ o%**!!!!!!!!!!!!*****%%%%oooeee&&&##@@@ %*!!!:::::::::::::!!!!!****%%%oooeee&&&##@@@@ %*!!:::............:::::!!!!****%%%oooeee&&###@@@@@ %*!::...... ........::::!!!!***%%%oooeee&&&##@@@@@@ %!!::... .....::::!!!!***%%%oooeee&&&##@@@@@@@ %*!::... .....::::!!!****%%%oooee&&&###@@@@@@@@ *!::... .....:::!!!!***%%%oooeee&&&###@@@@@@@@ o*!::.. .....::::!!!***%%%oooeee&&&###@@@@@@@@@@ o*!::.. .....::::!!!***%%%oooeee&&&####@@@@@@@@@@ o*!::... ....::::!!!!***%%%oooeee&&&&###@@@@@@@@@@@ o*!!::.. .....::::!!!****%%%oooeee&&&####@@@@@@@@@@@@ %*!::... .....::::!!!!***%%%%oooeee&&&####@@@@@@@@@@@@ o%*!::.... .....::::!!!!****%%%oooeeee&&&###@@@@@@@@@@@@@@ %**!:::.... ......::::!!!!****%%%ooooeee&&&####@@@@@@@@@@@@@@ e%**!!::..... .......:::::!!!!****%%%ooooeee&&&&####@@@@@@@@@@@@@@@ o%**!!::::.....................:::::!!!!*****%%%ooooeee&&&&####@@@@@@@@@@@@@@@@ o%%**!!:::::...............:::::::!!!!!****%%%%ooooeeee&&&####@@@@@@@@@@@@@@@@@ eo%***!!!:::::::......:::::::::!!!!!!****%%%%%ooooeee&&&&####@@@@@@@@@@@@@@@@@@ eo%%***!!!!:::::::::::::::::!!!!!!******%%%%ooooeeee&&&&####@@@@@@@@@@@@@@@@@@@ eeo%%****!!!!!!!!::::!!!!!!!!!!******%%%%%oooooeeee&&&&####@@@@@@@@@@@@@@@@@@@@ &eoo%%%*****!!!!!!!!!!!!!!!********%%%%%oooooeeee&&&&&####@@@@@@@@@@@@@@@@@@@@@ #&eooo%%%%*********************%%%%%%ooooooeeee&&&&&#####@@@@@@@@@@@@@@@@@@@@@@ &&eeooo%%%%%%************%%%%%%%%ooooooeeeee&&&&&#####@@@@@@@@@@@@@@@@@@@@@@@ #&&eeeoooo%%%%%%%%%%%%%%%%%%%oooooooeeeeee&&&&&#####@@@@@@@@@@@@@@@@@@@@@@@@@ ##&&eeeeoooooooooooooooooooooooeeeeeee&&&&&&#####@@@@@@@@@@@@@@@@@@@@@@@@@@ @##&&&eeeeeeooooooooooooooeeeeeeeee&&&&&&######@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@##&&&&&eeeeeeeeeeeeeeeeeeee&&&&&&&&#######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@###&&&&&&&&&&&&&&&&&&&&&&&&&&########@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@######&&&&&&&&&&&&&&&##########@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@#######################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@########@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@ o%%%%%%ooe&#@ *!::...:::!!*%%oe&&#@ *:. ..::!!*%ooe&#@@@ *: ..:!!*%ooe&#@@@@ !. ..::!*%%oe&&#@@@@ !. ..::!*%%oee&#@@@@@ !: ..:!!*%%oe&&#@@@@@@ %!. ..:!!**%ooe&&#@@@@@@@ %!:. ..::!!**%ooe&&##@@@@@@@ %!::.. ...:::!!*%%ooee&##@@@@@@@@ o*!!::.......:::!!!**%%oee&&##@@@@@@@@@ eo%*!!!!:::!!!!!**%%%ooee&&##@@@@@@@@@@ #eo%%**********%%%ooeee&&##@@@@@@@@@@@@ #&eooo%%%%%%ooooeee&&&###@@@@@@@@@@@@ ##&&eeeeeeeeee&&&&###@@@@@@@@@@@@@@ @@##&&&&&&&&#####@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@ ok ### PGM output The same program as the ASCII one is translated to produce a PGM portable pixmap image file. : 3dup 2 pick 2 pick 2 pick ; : sqrt ( u -- sqrt ) ( Babylonian method ) dup 2/ ( first square root guess is half ) dup 0= if drop exit then ( sqrt[0]=0, sqrt[1]=1 ) begin dup >r 2dup / r> + 2/ ( stack: square old-guess new-guess ) 2dup > while ( as long as guess is decreasing ) nip repeat ( forget old-guess and repeat ) drop nip ; : normalize ( x1 y1 z1 -- x1' y1' z1' ) ( normalise down to 1000 ) 3dup dup * rot dup * rot dup * + + sqrt 1000 / >r ( length ) r@ / rot r@ / rot r> / rot ; : r2-y2-x2 ( x y r -- z2 ) dup * swap dup * - swap dup * - ; 0 value fileidstore : image-open ( r -- ) outfile-id to fileidstore s" sphere.pgm" w/o create-file throw to outfile-id s\" P2\n" type 2* dup . . s\" \n255" type ; : image-close outfile-id close-file throw fileidstore to outfile-id ; : map-to-shade 255 * 1000 / 1 max 255 min ; : dot-light ( x y z -- i ) ( hard coded light vector z, y, x ) -770 * rot 461 * rot 461 * + + 0 min 1000 / ; : intensity ( x y z -- u ) dot-light dup * 1000 / map-to-shade ; : pixel ( x y r -- c ) 3dup r2-y2-x2 dup 0> if ( if in disk ) sqrt nip normalize intensity ( z=sqrt[r2-x2-y2] ) else 2drop 2drop 255 ( else blank ) then ; : draw ( r -- ) ( r x1000 ) dup image-open 1000 * dup dup negate do cr dup dup negate do dup I 500 + J 500 + rot pixel . 1000 +loop 1000 +loop drop image-close ; 200 draw  ## Frink This program not only draws a sphere and renders it onscreen projected on the x,y, and z axes but also outputs a .stl file for 3-D printing or display in a 3-D modeling package like MeshLab! Frink has built-in routines for 3-D modeling and can emit STL files or Wavefront OBJ files natively! Frink will let you print a sphere that you can hold in your hand! res = 254 / in v = callJava["frink.graphics.VoxelArray", "makeSphere", [1/2 inch res]] v.projectX[undef].show["X"] v.projectY[undef].show["Y"] v.projectZ[undef].show["Z"] filename = "sphere.stl" print["Writing$filename..."]
w = new Writer[filename]
w.println[v.toSTLFormat["sphere", 1/(res mm)]]
w.close[]
println["done."]

## FutureBasic

_window = 1
begin enum output 1
_sphereImageView
end enum

void local fn BuildWindow
CGRect  r = fn CGRectMake( 0, 0, 400, 400 )

r = fn CGRectMake( 20, 20, 360, 360 )
imageview _sphereImageView, YES, , r, NSImageScaleAxesIndependently, NSImageAlignCenter, NSImageFrameNone, _window
end fn

local fn SphereImageWithCIFilter( imageDimension as NSUInteger, sphereColor as ColorRef, backgroundColor as ColorRef, radiusBlur as float, radiusSphere as float ) as ImageRef
CIVectorRef    civ = fn CIVectorWithXY( imageDimension/2, imageDimension/2 )
CIFilterSetDefaults( filter )
ObjectSetValueForKey( filter, civ, @"inputCenter" )
ObjectSetValueForKey( filter, fn CIColorWithCGColor( fn ColorCGColor( sphereColor     ) ), @"inputColor0" )
ObjectSetValueForKey( filter, fn CIColorWithCGColor( fn ColorCGColor( backgroundColor ) ), @"inputColor1" )

ImageRef resultImage = fn ImageWithSize( fn CGSizeMake( imageDimension, imageDimension ) )
ImageLockFocus( resultImage )
CIImageDrawAtPoint( fn CIFilterOutputImage( filter ), CGPointZero, fn CGRectMake( 0, 0, imageDimension, imageDimension ), NSCompositeDestinationAtop, 1.0 )
ImageUnlockFocus( resultImage )
end fn = resultImage

local fn BuildSphere
ImageRef sphereImage = fn SphereImageWithCIFilter( 340, fn ColorWithRGB( 0.988, 0.335, 0.176, 1.0 ), fn ColorBlack, 0.0, 125.0 )
ImageViewSetImage( _sphereImageView, sphereImage )
end fn

fn BuildWindow
fn BuildSphere

HandleEvents
Output:

## Go

Translation of: C

Using image library rather than ASCII art.

package main

import (
"fmt"
"image"
"image/color"
"image/png"
"math"
"os"
)

type vector [3]float64

func normalize(v *vector) {
invLen := 1 / math.Sqrt(dot(v, v))
v[0] *= invLen
v[1] *= invLen
v[2] *= invLen
}

func dot(x, y *vector) float64 {
return x[0]*y[0] + x[1]*y[1] + x[2]*y[2]
}

func drawSphere(r int, k, amb float64, dir *vector) *image.Gray {
w, h := r*4, r*3
img := image.NewGray(image.Rect(-w/2, -h/2, w/2, h/2))
vec := new(vector)
for x := -r; x < r; x++ {
for y := -r; y < r; y++ {
if z := r*r - x*x - y*y; z >= 0 {
vec[0] = float64(x)
vec[1] = float64(y)
vec[2] = math.Sqrt(float64(z))
normalize(vec)
s := dot(dir, vec)
if s < 0 {
s = 0
}
lum := 255 * (math.Pow(s, k) + amb) / (1 + amb)
if lum < 0 {
lum = 0
} else if lum > 255 {
lum = 255
}
img.SetGray(x, y, color.Gray{uint8(lum)})
}
}
}
return img
}

func main() {
dir := &vector{-30, -30, 50}
normalize(dir)
img := drawSphere(200, 1.5, .2, dir)
f, err := os.Create("sphere.png")
if err != nil {
fmt.Println(err)
return
}
if err = png.Encode(f, img); err != nil {
fmt.Println(err)
}
if err = f.Close(); err != nil {
fmt.Println(err)
}
}


import Graphics.Rendering.OpenGL.GL
import Graphics.UI.GLUT.Objects
import Graphics.UI.GLUT

setProjection :: IO ()
setProjection = do
matrixMode $= Projection ortho (-1) 1 (-1) 1 0 (-1) grey1,grey9,red,white :: Color4 GLfloat grey1 = Color4 0.1 0.1 0.1 1 grey9 = Color4 0.9 0.9 0.9 1 red = Color4 1 0 0 1 white = Color4 1 1 1 1 setLights :: IO () setLights = do let l = Light 0 ambient l$= grey1
diffuse  l $= white specular l$= white
position l $= Vertex4 (-4) 4 3 (0 :: GLfloat) light l$= Enabled
lighting   $= Enabled setMaterial :: IO () setMaterial = do materialAmbient Front$= grey1
materialDiffuse   Front $= red materialSpecular Front$= grey9
materialShininess Front $= (32 :: GLfloat) display :: IO() display = do clear [ColorBuffer] renderObject Solid$ Sphere' 0.8 64 64
swapBuffers

main :: IO()
main = do
_ <- getArgsAndInitialize
_ <- createWindow "Sphere"
clearColor $= Color4 0.0 0.0 0.0 0.0 setProjection setLights setMaterial displayCallback$= display
mainLoop


### ASCII art

Translation of: Python
import Data.List (genericLength)

dot a b = sum $zipWith (*) a b normalize x = (/ sqrt (x dot x)) <$> x

sphere r k amb light = unlines $[ [ if x*x + y*y <= r*r then let vec = normalize [x, y, sqrt (r*r-x*x-y*y)] b = (light dot vec) ** k + amb intensity = (1 - b)*(n - 1) in shades !! round ((0 max intensity) min n) else ' ' | y <- map (/2.12) [- 2*r - 0.5 .. 2*r + 0.5] ] | x <- [ - r - 0.5 .. r + 0.5] ]  λ> putStrLn$ sphere 10 4 0.1 (normalize [30,30,-50])

#%%%%%%%####&&
eoo*****oooee%%%###&&&
eo*!!::::!!!**ooee%%%###&&&&
e*!::......::!!**ooee%%####&&&&&
%o!::.........::!!**ooee%%###&&&&&&&
eo!::..........::!!**ooee%%###&&&&&&&&
%o*!:..........::!!**ooee%%%###&&&&&&&&&
#eo*!::.......:::!!**ooeee%%####&&&&&&&&&&
%eo*!!:::::::::!!***ooeee%%####&&&&&&&&&&&
%eeo**!!!!!!!!****ooeee%%%####&&&&&&&&&&&&
#%eeooo*******ooooeee%%%%####&&&&&&&&&&&&&
##%%eeeoooooooeeeee%%%%####&&&&&&&&&&&&&&&
&###%%%%eeeeee%%%%%%######&&&&&&&&&&&&&&&#
&&####%%%%%%%%########&&&&&&&&&&&&&&&&&&
&&&##############&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&#



## Icon and Unicon

Unicon provides a built-in interface to openGL including some higher level abstractions (for more information see Unicon Technical References, 3D Graphics). The example below draws a blue sphere on a black background and waits for input to quit.

procedure main()
W := open("Demo", "gl", "size=400,400", "bg=black") | stop("can't open window!")
WAttrib(W, "slices=40", "rings=40", "light0=on, ambient white; diffuse gold; specular gold; position 5, 0, 0" )
Fg(W, "emission blue")
DrawSphere(W, 0, 0, -5, 1)
Event(W)
end


## J

### Demo Solution

The simplest way to draw a sphere is to run the sphere demo code from J's simple demos. (This assumes J version 6.)

Normally you would bring up this demo by using the menu system:

Studio
> Demos...
> opengl simple... [ok]
> sphere [Run]


But bringing up the example with a line of code is trivial enough:

load '~system/examples/graphics/opengl/simple/sphere.ijs'


(Note that this example has been removed from recent versions of J, but still works for J version 5 and version 6.)

### Raytracing Solution

Here's a version using raytracing computed in J. luminosity is an array of luminosity values with theoretical maximum 1 and minimum 0, and viewmat is used to display this.

'R k ambient' =. 10 2 0.4
light =. (% +/&.:*:) 30 30 _50
pts =. (0&*^:(0={:))@:(,,(0>.(*:R)-+)&.*:)"0/~ i:15j200
luminosity =. (>:ambient) %~ (ambient * * +/&.:*:"1 pts) + k^~ 0>. R%~ pts +/@:*"1 -light

torgb =. 256 #. [: <. 255 255 255 *"1 0 ]
'rgb' viewmat torgb luminosity


## Java

Translation of: C
public class Sphere{
static char[] shades = {'.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@'};

static double[] light = { 30, 30, -50 };
private static void normalize(double[] v){
double len = Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] /= len; v[1] /= len; v[2] /= len;
}

private static double dot(double[] x, double[] y){
double d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
return d < 0 ? -d : 0;
}

public static void drawSphere(double R, double k, double ambient){
double[] vec = new double[3];
for(int i = (int)Math.floor(-R); i <= (int)Math.ceil(R); i++){
double x = i + .5;
for(int j = (int)Math.floor(-2 * R); j <= (int)Math.ceil(2 * R); j++){
double y = j / 2. + .5;
if(x * x + y * y <= R * R) {
vec[0] = x;
vec[1] = y;
vec[2] = Math.sqrt(R * R - x * x - y * y);
normalize(vec);
double b = Math.pow(dot(light, vec), k) + ambient;
int intensity = (b <= 0) ?
(int)Math.max((1 - b) * (shades.length - 1), 0);
} else
System.out.print(' ');
}
System.out.println();
}
}

public static void main(String[] args){
normalize(light);
drawSphere(20, 4, .1);
drawSphere(10, 2, .4);
}
}

Output:
                               &&&&&&&&&&#######
&eeeeeeeeeeeeeeee&&&&&&#######%
&eoooo*******oooooooeeeee&&&&&########%
eoo****!!!!!!!!******oooooeeee&&&&&########%%
eoo**!!!!::::::::!!!!!*****ooooeeee&&&&&########%%%
eo**!!::::::...:::::::!!!!!***ooooeeee&&&&&########%%%%
eo*!!:::.............:::::!!!!***ooooeeee&&&&&########%%%%%
eo*!!:::.................::::!!!!***ooooeeee&&&&#########%%%%%%
eo*!!::....................::::!!!****oooeeee&&&&&#########%%%%%%
&o**!::......................::::!!!****oooeeee&&&&&##########%%%%%%%
&o**!::.......................::::!!!****oooeeee&&&&&##########%%%%%%%%
&oo*!!::.......................:::!!!!***ooooeeee&&&&&##########%%%%%%%%%
&eo*!!::.......................::::!!!****ooooeeee&&&&&##########%%%%%%%%%%
eo**!!::......................::::!!!!***ooooeeeee&&&&&##########%%%%%%%%%%
&eo**!!:::...................:::::!!!!****ooooeeee&&&&&###########%%%%%%%%%%%
eeo**!!::::................:::::!!!!!****ooooeeee&&&&&&###########%%%%%%%%%%%
&eeo***!!:::::...........::::::!!!!!****oooooeeee&&&&&&###########%%%%%%%%%%%%%
&eeoo**!!!!::::::::::::::::::!!!!!*****ooooeeeee&&&&&&############%%%%%%%%%%%%%
&eeooo***!!!!::::::::::::!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%%
&&eeooo***!!!!!!!!!!!!!!!!!!!******oooooeeeeee&&&&&&############%%%%%%%%%%%%%%%
&&eeeooo******!!!!!!!!!!********ooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%%
#&&eeeooooo******************oooooooeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%%
#&&&eeeeoooooooo******oooooooooooeeeeeee&&&&&&&&#############%%%%%%%%%%%%%%%%%%
##&&&&eeeeeooooooooooooooooooeeeeeeee&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%
##&&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&################%%%%%%%%%%%%%%%%%%%
####&&&&&&eeeeeeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%%
#####&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%%
%#######&&&&&&&&&&&&&&&&&&&&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%
%###########&&&&&&&&&&&&&#######################%%%%%%%%%%%%%%%%%%%%%%%%%
%############################################%%%%%%%%%%%%%%%%%%%%%%%%%%
%%#######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%#################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%#########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%#############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%

::...:::!!!*o
..............::!!*oo
..................::!!**ooe
.....................::!!**ooee
.......................::!!**ooee
........................::!!**oooee
.........................::!!**oooeee
:........................::!!!**oooeeee
........................::!!!**ooooeeee
:......................::!!!***oooeeeee
:....................:::!!!***oooeeeeee
!:.................:::!!!****oooeeeeeee
*!:::...........::::!!!!***ooooeeeeeeee
*!!!:::::::::::!!!!!****oooooeeeeeeee
o**!!!!!!!!!!!!!*****oooooeeeeeeeee
oo**************ooooooeeeeeeeeeee
eoooooooooooooooooeeeeeeeeeeeee
eeeooooooooeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeee


## JavaScript

Translation of: C

This Javascript entry uses an HTML wrapper to offer easy running and some interactivity. It is made as such, though, that the entire HTML wrapper can be removed (except for a canvas with id c) and still work. If you remove the HTML, call the draw_sphere function to draw the thing.

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>Draw a sphere</title>
<script>
var light=[30,30,-50],gR,gk,gambient;

function normalize(v){
var len=Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
v[0]/=len;
v[1]/=len;
v[2]/=len;
return v;
}

function dot(x,y){
var d=x[0]*y[0]+x[1]*y[1]+x[2]*y[2];
return d<0?-d:0;
}

function draw_sphere(R,k,ambient){
var i,j,intensity,b,vec,x,y,cvs,ctx,imgdata,idx;
cvs=document.getElementById("c");
ctx=cvs.getContext("2d");
cvs.width=cvs.height=2*Math.ceil(R)+1;
imgdata=ctx.createImageData(2*Math.ceil(R)+1,2*Math.ceil(R)+1);
idx=0;
for(i=Math.floor(-R);i<=Math.ceil(R);i++){
x=i+.5;
for(j=Math.floor(-R);j<=Math.ceil(R);j++){
y=j+.5;
if(x*x+y*y<=R*R){
vec=[x,y,Math.sqrt(R*R-x*x-y*y)];
vec=normalize(vec);
b=Math.pow(dot(light,vec),k)+ambient;
intensity=(1-b)*256;
if(intensity<0)intensity=0;
if(intensity>=256)intensity=255;
imgdata.data[idx++]=imgdata.data[idx++]=255-~~(intensity); //RG
imgdata.data[idx++]=imgdata.data[idx++]=255; //BA
} else {
imgdata.data[idx++]=imgdata.data[idx++]=imgdata.data[idx++]=imgdata.data[idx++]=255; //RGBA
}
}
}
ctx.putImageData(imgdata,0,0);
}

light=normalize(light);
</script>
R=<input type="range" id="R" name="R" min="5" max="500" value="200" step="5" onchange="document.getElementById('lR').innerHTML=gR=parseFloat(this.value);draw_sphere(gR,gk,gambient)">
<label for="R" id="lR">200</label><br>
k=<input type="range" id="k" name="k" min="0" max="10" value="4" step=".25" onchange="document.getElementById('lk').innerHTML=gk=parseFloat(this.value);draw_sphere(gR,gk,gambient)">
<label for="k" id="lk">4</label><br>
ambient=<input type="range" id="ambient" name="ambient" min="0" max="1" value=".2" step=".05" onchange="document.getElementById('lambient').innerHTML=gambient=parseFloat(this.value);draw_sphere(gR,gk,gambient)">
<label for="ambient" id="lambient">0.2</label><br>
<canvas id="c">Unsupportive browser...</canvas><br>
</body>
</html>


## jq

Works with: jq version 1.4

The approach adopted here is to generate an SVG file, which may then be viewed, for example, in a web browser.

def svg:
"<svg width='100%' height='100%' version='1.1'
xmlns='http://www.w3.org/2000/svg'

# A radial gradient to make a circle look like a sphere.
# "colors" should be [startColor, intermediateColor, endColor]
# or null for ["white", "teal", "black"]
"<defs>
<radialGradient id = '\(id)' cx = '30%' cy = '30%' r = '100%' fx='10%' fy='10%' >
<stop stop-color = '\(colors[0]//"white")' offset =   '0%'/>
<stop stop-color = '\(colors[1]//"teal")'  offset =  '50%'/>
<stop stop-color = '\(colors[1]//"black")' offset = '100%'/>
</defs>" ;

"<circle fill='url(#\(gradientId))' cx='\(cx)' cy='\(cy)' r='\(r)' />" ;

Example:

def draw_sphere:
svg,
"<title>Teal sphere</title>",
"</svg>" ;

draw_sphere
Output:
$jq -r -n -f spheres.jq > spheres.svg  One way to view the output as an image is to point your browser to the generated SVG. ## Julia ### ASCII Text Translation of: C function draw_sphere(r, k, ambient, light) shades = ('.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@') for i in floor(Int, -r):ceil(Int, r) x = i + 0.5 line = IOBuffer() for j in floor(Int, -2r):ceil(2r) y = j / 2 + 0.5 if x ^ 2 + y ^ 2 ≤ r ^ 2 v = normalize([x, y, sqrt(r ^ 2 - x ^ 2 - y ^ 2)]) b = dot(light, v) ^ k + ambient intensity = ceil(Int, (1 - b) * (length(shades) - 1)) if intensity < 1 intensity = 1 end if intensity > length(shades) intensity = length(shades) end print(shades[intensity]) else print(' ') end end println() end end light = normalize([30, 30, -50]) draw_sphere(20, 4, 0.1, light) draw_sphere(10, 2, 0.4, light)  ### Graphical # run from REPL using Makie φ = 0:π/100:2π θ = 0:π/200:π x = [cos(θ) * sin(φ) for θ in θ, φ in φ] y = [sin(θ)*sin(φ) for θ in θ, φ in φ] z = [cos(φ) for θ in θ, φ in φ] surface(x, y, z, backgroundcolor = :black, show_axis = false)  ## Kotlin Translation of: C // version 1.0.6 const val shades = ".:!*oe&#%@" val light = doubleArrayOf(30.0, 30.0, -50.0) fun normalize(v: DoubleArray) { val len = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) v[0] /= len; v[1] /= len; v[2] /= len } fun dot(x: DoubleArray, y: DoubleArray): Double { val d = x[0] * y[0] + x[1] * y[1] + x[2] * y[2] return if (d < 0.0) -d else 0.0 } fun drawSphere(r: Double, k: Double, ambient: Double) { val vec = DoubleArray(3) var intensity: Int var b : Double var x: Double var y: Double for (i in Math.floor(-r).toInt() .. Math.ceil(r).toInt()) { x = i + 0.5 for (j in Math.floor(-2.0 * r).toInt() .. Math.ceil(2.0 * r).toInt()) { y = j / 2.0 + 0.5 if (x * x + y * y <= r * r) { vec[0] = x vec[1] = y vec[2] = Math.sqrt(r * r - x * x - y * y) normalize(vec) b = Math.pow(dot(light, vec), k) + ambient intensity = ((1.0 - b) * (shades.length - 1)).toInt() if (intensity < 0) intensity = 0 if (intensity >= shades.length - 1) intensity = shades.length - 2 print(shades[intensity]) } else print(' ') } println() } } fun main(args: Array<String>) { normalize(light) drawSphere(20.0, 4.0, 0.1) drawSphere(10.0, 2.0, 0.4) }  Output:  &&&&&&&&&&####### &eeeeeeeeeeeeeeee&&&&&&#######% &eoooo*******oooooooeeeee&&&&&########% eoo****!!!!!!!!******oooooeeee&&&&&########%% eoo**!!!!::::::::!!!!!*****ooooeeee&&&&&########%%% eo**!!::::::...:::::::!!!!!***ooooeeee&&&&&########%%%% eo*!!:::.............:::::!!!!***ooooeeee&&&&&########%%%%% eo*!!:::.................::::!!!!***ooooeeee&&&&#########%%%%%% eo*!!::....................::::!!!****oooeeee&&&&&#########%%%%%% &o**!::......................::::!!!****oooeeee&&&&&##########%%%%%%% &o**!::.......................::::!!!****oooeeee&&&&&##########%%%%%%%% &oo*!!::.......................:::!!!!***ooooeeee&&&&&##########%%%%%%%%% &eo*!!::.......................::::!!!****ooooeeee&&&&&##########%%%%%%%%%% eo**!!::......................::::!!!!***ooooeeeee&&&&&##########%%%%%%%%%% &eo**!!:::...................:::::!!!!****ooooeeee&&&&&###########%%%%%%%%%%% eeo**!!::::................:::::!!!!!****ooooeeee&&&&&&###########%%%%%%%%%%% &eeo***!!:::::...........::::::!!!!!****oooooeeee&&&&&&###########%%%%%%%%%%%%% &eeoo**!!!!::::::::::::::::::!!!!!*****ooooeeeee&&&&&&############%%%%%%%%%%%%% &eeooo***!!!!::::::::::::!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%% &&eeooo***!!!!!!!!!!!!!!!!!!!******oooooeeeeee&&&&&&############%%%%%%%%%%%%%%% &&eeeooo******!!!!!!!!!!********ooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%% #&&eeeooooo******************oooooooeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%% #&&&eeeeoooooooo******oooooooooooeeeeeee&&&&&&&&#############%%%%%%%%%%%%%%%%%% ##&&&&eeeeeooooooooooooooooooeeeeeeee&&&&&&&&&##############%%%%%%%%%%%%%%%%%%% ##&&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&################%%%%%%%%%%%%%%%%%%% ####&&&&&&eeeeeeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%% #####&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%% %#######&&&&&&&&&&&&&&&&&&&&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%% %###########&&&&&&&&&&&&&#######################%%%%%%%%%%%%%%%%%%%%%%%%% %############################################%%%%%%%%%%%%%%%%%%%%%%%%%% %%#######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%#################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%#########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%#############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%% ::...:::!!!*o ..............::!!*oo ..................::!!**ooe .....................::!!**ooee .......................::!!**ooee ........................::!!**oooee .........................::!!**oooeee :........................::!!!**oooeeee ........................::!!!**ooooeeee :......................::!!!***oooeeeee :....................:::!!!***oooeeeeee !:.................:::!!!****oooeeeeeee *!:::...........::::!!!!***ooooeeeeeeee *!!!:::::::::::!!!!!****oooooeeeeeeee o**!!!!!!!!!!!!!*****oooooeeeeeeeee oo**************ooooooeeeeeeeeeee eoooooooooooooooooeeeeeeeeeeeee eeeooooooooeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeee  ## Lingo ---------------------------------------- -- Draw a circle -- @param {image} img -- @param {integer} x -- @param {integer} y -- @param {integer} r -- @param {integer} lineSize -- @param {color} drawColor ---------------------------------------- on circle (img, x, y, r, lineSize, drawColor) props = [:] props[#shapeType] = #oval props[#lineSize] = lineSize props[#color] = drawColor img.draw(x-r, y-r, x+r, y+r, props) end ## Logo Drawing a sphere is actually very simple in logo, using the perspective function to make life easier. Works with: MSWlogo to sphere :r cs perspective ht ;making the room ready to use repeat 180 [polystart circle :r polyend down 1] polyview end ## Lua Translation of: C Works with: Lua version 5.1.4 require ("math") shades = {'.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@'} function normalize (vec) len = math.sqrt(vec[1]^2 + vec[2]^2 + vec[3]^2) return {vec[1]/len, vec[2]/len, vec[3]/len} end light = normalize{30, 30, -50} function dot (vec1, vec2) d = vec1[1]*vec2[1] + vec1[2]*vec2[2] + vec1[3]*vec2[3] return d < 0 and -d or 0 end function draw_sphere (radius, k, ambient) for i = math.floor(-radius),-math.floor(-radius) do x = i + .5 local line = '' for j = math.floor(-2*radius),-math.floor(-2*radius) do y = j / 2 + .5 if x^2 + y^2 <= radius^2 then vec = normalize{x, y, math.sqrt(radius^2 - x^2 - y^2)} b = dot(light,vec) ^ k + ambient intensity = math.floor ((1 - b) * #shades) line = line .. (shades[intensity] or shades[1]) else line = line .. ' ' end end print (line) end end draw_sphere (20, 4, 0.1) draw_sphere (10, 2, 0.4)  Output:  &&&&&&&&&&&&##### &eeeoooooooooeeeeee&&&&&####### eooo*************oooooeeee&&&&&######## eo**!!!!!!!!!!!!!!!*****ooooeeee&&&&######### eo*!!!:::::...:::::::!!!!****oooeeee&&&&&########## o**!:::..............::::!!!!***ooooeee&&&&&########### o*!!::...................::::!!!***ooooeee&&&&&############ eo*!::......................::::!!!***oooeeee&&&&&############# o*!::.........................:::!!!***ooooeee&&&&&############## &o*!::..........................:::!!!***ooooeeee&&&&###############% eo*!::...........................:::!!!***ooooeeee&&&&&###############% eo*!::............................:::!!!***ooooeeee&&&&&###############%% &o*!!::...........................:::!!!!***oooeeee&&&&&#################%% eo*!!:...........................::::!!!***ooooeeee&&&&&#################%% eo**!!::.........................::::!!!****oooeeee&&&&&&#################%%% eo**!!::.......................::::!!!!****oooeeeee&&&&&##################%%% &eo**!!:::....................:::::!!!!***ooooeeeee&&&&&&##################%%%% &eoo**!!::::................:::::!!!!****ooooeeeee&&&&&&###################%%%% &eoo***!!!:::::........:::::::!!!!!****oooooeeeee&&&&&&###################%%%%% &eeoo***!!!!:::::::::::::::!!!!!!*****ooooeeeee&&&&&&&####################%%%%% &&eeoo****!!!!!!!!!!!!!!!!!!!!*****oooooeeeeee&&&&&&######################%%%%% &&eeeooo******!!!!!!!!!!!*******ooooooeeeeee&&&&&&&######################%%%%%% #&&eeeooooo******************oooooooeeeeee&&&&&&&#######################%%%%%%% ##&&&eeeeoooooooooo*ooooooooooooeeeeeeee&&&&&&&&#######################%%%%%%%% ##&&&eeeeeeooooooooooooooooeeeeeeeee&&&&&&&&&########################%%%%%%%% ###&&&&&eeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&&##########################%%%%%%%%% ####&&&&&&&eeeeeeeeeeeeeee&&&&&&&&&&&&############################%%%%%%%%% ######&&&&&&&&&&&&&&&&&&&&&&&&&&&&&##############################%%%%%%%%%% ########&&&&&&&&&&&&&&&&&&&&&&################################%%%%%%%%%%% ###############&&&&&#######################################%%%%%%%%%%%% #########################################################%%%%%%%%%%%% #####################################################%%%%%%%%%%%% #################################################%%%%%%%%%%%%%% #############################################%%%%%%%%%%%%%% ########################################%%%%%%%%%%%%%%% ##################################%%%%%%%%%%%%%%%%% %##########################%%%%%%%%%%%%%%%%%% %%%%############%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%% ........::!!* ...............::!!*o ....................::!**oo .......................::!**ooo ........................::!!**ooo .........................::!!**oooo ..........................::!!**ooooe ...........................::!!**ooooee ..........................::!!***ooooee .........................::!!!**oooooee .......................:::!!!**oooooeee :.....................::!!!***ooooooeee !::................:::!!!!***ooooooeeee !!::..........:::::!!!****ooooooeeeee *!!!::::::::::!!!!!****oooooooeeeee o***!!!!!!!!!******ooooooooeeeeee ooo***********ooooooooooeeeeeee oooooooooooooooooooeeeeeeee eooooooooooeeeeeeeeee eeeeeeeeeeeee  ## M2000 Interpreter Module CheckIt { Er$="Pset is a new statement"
If Version<9.4 Then Error Er$If Version=9.4 then If revision<26 then Error Er$
Form 60, 40
Cls 0 ' Black
Pen 14 ' Yellow
Set Fast !
Refresh 500
Module Sphere (R as long, X0 as long, Y0 as long, fun){
R2 = R * R
Def Long X, Y, D2
Let Scale=twipsx/R*13.5
For Y = -R To R  step twipsx  {
Move X0-R, Y+Y0
For X = -R To R step twipsy  {
D2 = X **2 + Y **2
IF R2>D2 THEN Pset Fun(Max.Data(Min.Data((Sqrt(R2 - D2) - ( X + Y) / 2 )*Scale ,255),0))
Step twipsx
}
}
}
Blue=lambda (c)->{
c1=c/4+192
=Color(c,c,c1)
}
Blue1=lambda (c)->{
c1=c/4+Random(150,192)
=Color(c,c,c1)
}
Mystery=lambda m=1 (c)->{
c1=c/4+m
m+=10
if m>192 then m=1
=Color(c,c,c1)
}
Mystery2=lambda m=1, p=true  (c)->{
c1=c/4+m
if p then m+=10
Else m=-10
if m>192 then m-=10 : p=false
If m<0 then m+=10: p=true
=Color(c,c,c1)
}
Buffer Alfa as byte*8
Trans =lambda  Alfa (c) -> {
Return Alfa, 0:=-point as long
Return Alfa, 4:=-color(c,c, c/4+192) as long
for i=0 to 2: Return Alfa, i:=(Eval(Alfa, i)+Eval(Alfa, i+4))/2: Next i
=-Eval(Alfa, 0 as long)
}
Sphere 2400, 9000,7000, Blue
Sphere 800, 6000, 7000, Blue1
Sphere 1200, 5000,5000, Mystery
Sphere 1200, 10000,6000, Mystery2
Sphere 1200, 8000,5000, trans
}
Checkit

[[3]image]

## Maple

plots[display](plottools[sphere](), axes = none, style = surface);

## Mathematica / Wolfram Language

Mathematica has many 3D drawing capabilities. To create a sphere with radius one centered at (0,0,0):

Graphics3D[Sphere[{0,0,0},1]]


## MATLAB

To create the unit sphere:

figure; sphere


## Maxima

/* Two solutions */
plot3d(1, [theta, 0, %pi], [phi, 0, 2 * %pi],
[transform_xy, spherical_to_xyz], [grid, 30, 60],
[box, false], [legend, false])$load(draw)$
draw3d(xu_grid=30, yv_grid=60, surface_hide=true,
parametric_surface(cos(phi)*sin(theta),
sin(phi)*sin(theta),
cos(theta),

## Perl

Translation of: Raku

This produces a PGM image which can't be uploaded on rosettacode at the moment. It looks similar as the Raku solution, though.

use strict;
use warnings;

my $x = my$y = 255;
$x |= 1; # must be odd my$depth = 255;

my $light = Vector->new(rand, rand, rand)->normalized; print "P2\n$x $y\n$depth\n";

my ($r,$ambient) = (($x - 1)/2, 0); my ($r2) = $r ** 2; { for my$x (-$r ..$r) {
my $x2 =$x**2;
for my $y (-$r .. $r) { my$y2 = $y**2; my$pixel = 0;
if ($x2 +$y2 < $r2) { my$v = Vector->new($x,$y, sqrt($r2 -$x2 - $y2))->normalized; my$I = $light .$v + $ambient;$I = $I < 0 ? 0 :$I > 1 ? 1 : $I;$pixel = int($I *$depth);
}
print $pixel; print$y == $r ? "\n" : " "; } } } package Vector { sub new { my$class = shift;
bless ref($_[0]) eq 'Array' ?$_[0] : [ @_ ], $class; } sub normalized { my$this = shift;
my $norm = sqrt($this . $this); ref($this)->new( map $_/$norm, @$this ); } use overload q{.} => sub { my ($a, $b) = @_; my$sum = 0;
for (0 .. @$a - 1) {$sum += $a->[$_] * $b->[$_]
}
return $sum; }, q{""} => sub { sprintf "Vector:[%s]", join ' ', @{shift()} }; }  ## Phix Library: Phix/pGUI Library: Phix/online Translation of: Go (Go gets credit for the dot/normalize/drawSphere routines, but this draws on screen rather than to png file) Sphere will resize to match the window. You can run this online here. Note fullscreen redraw can be quite slow. -- -- demo\rosetta\Draw_a_sphere.exw -- ============================== -- with javascript_semantics include pGUI.e constant title = "Draw a sphere" Ihandle dlg, canvas cdCanvas cddbuffer, cdcanvas function dot(sequence x, y) return sum(sq_mul(x,y)) end function function normalize(sequence v) atom len = sqrt(dot(v, v)) return iff(len=0?{0,0,0}:sq_mul(v,1/len)) end function procedure drawSphere(integer width, height, atom k, amb, sequence direction) atom t0 = time()+1, t1 = t0, lmul = 255/(1+amb) integer r = floor((min(width,height)-20)/2), cx = floor(width/2), cy = floor(height/2) for x=-r to r do if time()>t1 then -- Let the user know we aren't completely dead just yet IupSetStrAttribute(dlg,"TITLE","%s - drawing (%d%%)",{title,100*(x+r)/(2*r)}) t1 = time()+1 -- (as per DeathStar.exw, prevent "(Not Responding)" nonsense) if platform()!=JS then if IupLoopStep()=IUP_CLOSE then IupExitLoop() exit end if end if end if for y=-r to r do integer z = r*r-(x*x+y*y) if z>=0 then atom s = dot(direction, normalize({x,y,sqrt(z)})), l = iff(s<=0?0:power(s,k)) integer lum = and_bits(#FF,lmul*(l+amb)) cdCanvasPixel(cddbuffer, x+cx, y+cy, lum*#10101) end if end for end for if t1!=t0 then IupSetStrAttribute(dlg,"TITLE",title) end if end procedure function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/) integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE") cdCanvasActivate(cddbuffer) cdCanvasClear(cddbuffer) drawSphere(width,height,1.5,0.2,normalize({-30,-30,50})) cdCanvasFlush(cddbuffer) return IUP_DEFAULT end function function map_cb(Ihandle ih) cdcanvas = cdCreateCanvas(CD_IUP, ih) cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas) cdCanvasSetBackground(cddbuffer, CD_BLACK) return IUP_DEFAULT end function procedure main() IupOpen() canvas = IupCanvas("RASTERSIZE=340x340") IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"), "ACTION", Icallback("redraw_cb")}) dlg = IupDialog(canvas,TITLE="%s",{title}) IupShow(dlg) IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation if platform()!=JS then IupMainLoop() IupClose() end if end procedure main()  ## PicoLisp Library: GLUT This is for the 64-bit version. (load "@lib/openGl.l") (glutInit) (glutInitDisplayMode (| GLUT_RGBA GLUT_DOUBLE GLUT_ALPHA GLUT_DEPTH)) (glutInitWindowSize 400 400) (glutCreateWindow "Sphere") (glEnable GL_LIGHTING) (glEnable GL_LIGHT0) (glLightiv GL_LIGHT0 GL_POSITION (10 10 -10 0)) (glEnable GL_COLOR_MATERIAL) (glColorMaterial GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE) (glClearColor 0.3 0.3 0.5 0) (glColor4f 0.0 0.8 0.0 1.0) (displayPrg (glClear (| GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT)) (glutSolidSphere 0.9 40 32) (glFlush) (glutSwapBuffers) ) # Exit upon mouse click (mouseFunc '((Btn State X Y) (bye))) (glutMainLoop) Translation of: C (scl 24) (setq *Shades (list "." ":" "!" "*" "o" "e" "&" "#" "%" "@")) (setq *Light (list 30.0 30.0 -50.0)) (de normalize (V) (let Len (sqrt (sum (quote (X) (** X 2)) V)) (mapcar (quote (X) (*/ X 1.0 Len)) V))) (de dot (X Y) (let D (sum (quote (A B) (*/ A B 1.0)) X Y) (if (< D 0) (- D) 0))) (de floor (N) (* 1.0 (*/ (- N 0.5) 1.0))) (de ceil (N) (* 1.0 (*/ (+ N 0.5) 1.0))) (de drawSphere (R K Ambient) (let Vec NIL (for (I (floor (- R)) (<= I (ceil R)) (+ I 1.0)) (let X (+ I 0.5) (for (J (floor (* -2 R)) (<= J (ceil (* 2 R))) (+ J 1.0)) (let Y (+ (/ J 2) 0.5) (if (<= (+ (*/ X X 1.0) (*/ Y Y 1.0)) (*/ R R 1.0)) (prog (setq Vec (list X Y (sqrt (* 1.0 (- (*/ R R 1.0) (*/ X X 1.0) (*/ Y Y 1.0)))))) (setq Vec (normalize Vec)) (let (B NIL Intensity NIL) (setq B (+ (/ (** (dot *Light Vec) K) (** 1.0 (- K 1))) Ambient)) (setq Intensity (if (<= B 0) (- (length *Shades) 2) (max (format (round (*/ (- 1.0 B) (* (- (length *Shades) 1) 1.0) 1.0) 0)) 0))) (prin (nth *Shades (+ Intensity 1) 1)))) (prin " ")))) (prinl))))) (setq *Light (normalize *Light)) (drawSphere 20.0 4 0.1) (drawSphere 10.0 2 0.4) Output:  ##############%%% #&&eeeeeeeeeee&&&&&&######%%%%% &eeeoooooooooooooeeeee&&&&&######%%%%%% &eooo**************oooooeeee&&&&&#####%%%%%%% &eoo**!!!!!!!!!!!!!!*****ooooeeee&&&&######%%%%%%%% eoo**!!!::::::::::::!!!!****ooooeeee&&&&######%%%%%%%%% eoo*!!!::::.......::::::!!!!****oooeeee&&&&######%%%%%%%%%% &eo*!!:::..............::::!!!!***ooooeeee&&&&######%%%%%%%%%%% eo**!!::.................::::!!!****oooeeee&&&&######%%%%%%%%%%%% &eo*!!:::..................::::!!!!***oooeeee&&&&&######%%%%%%%%%%%%% &eo*!!:::...................::::!!!!***oooeeee&&&&&######%%%%%%%%%%%%%% &eo**!!::....................::::!!!****oooeeee&&&&&######%%%%%%%%%%%%%%% #eoo*!!:::...................::::!!!!***ooooeeee&&&&#######%%%%%%%%%%%%%%%% &eo**!!:::.................:::::!!!!****oooeeee&&&&&#######%%%%%%%%%%%%%%%% &eoo**!!::::...............:::::!!!!****ooooeeee&&&&#######%%%%%%%%%%%%%%%%%% &eoo**!!!::::...........::::::!!!!*****ooooeeee&&&&&#######%%%%%%%%%%%%%%%%%% #&eoo***!!!::::::::::::::::::!!!!!****ooooeeeee&&&&&#######%%%%%%%%%%%%%%%%%%%% #&eeoo***!!!!::::::::::::!!!!!!!*****ooooeeeee&&&&&#######%%%%%%%%%%%%%%%%%%%%% #&eeooo****!!!!!!!!!!!!!!!!!!******ooooeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%%%% #&&eeooo******!!!!!!!!!!!*******ooooooeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%%%%% #&&&eeooooo******************ooooooeeeeee&&&&&&########%%%%%%%%%%%%%%%%%%%%%%%% ##&&&eeeooooooo********oooooooooeeeeeee&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%% ###&&&eeeeeooooooooooooooooooeeeeeee&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%%% %###&&&&eeeeeeeeeeeoeeeeeeeeeeeee&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%%%% %####&&&&&eeeeeeeeeeeeeeeeee&&&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%#####&&&&&&&&&&&&&&&&&&&&&&&&&&&############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%#######&&&&&&&&&&&&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%############&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%##############################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%#######################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%#########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%% !::::::!!!**o ............:::!!**oe :................::!!**ooee :...................::!!**ooeee ......................::!!**ooeee .......................::!!**ooeeee .......................:::!!**ooeeeee :.......................::!!***ooeeeeee :......................::!!!**oooeeeeee :....................:::!!!**oooeeeeeee !:..................:::!!***oooeeeeeeee !!:..............::::!!!***oooeeeeeeeee *!!::::.....::::::!!!!***ooooeeeeeeeeee o*!!!!::::::!!!!!!****ooooeeeeeeeeeee o****!!!!!!!******oooooeeeeeeeeeeee eooo********oooooooeeeeeeeeeeeeee eeeoooooooooooeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeee  ## PostScript Gradient filled circle: %!PS-Adobe-3.0 %%BoundingBox 0 0 300 300 150 150 translate 0 0 130 0 360 arc /Pattern setcolorspace << /PatternType 2 /Shading << /ShadingType 3 /ColorSpace /DeviceRGB /Coords [-60 60 0 0 0 100] /Function << /FunctionType 2 /Domain [0 1] /C0 [1 1 1] /C1 [0 0 0] /N 2 >> >> >> matrix makepattern setcolor fill showpage %%EOF  ## POV-Ray This is what POVray was made for. An example with a sky, surface and transparency: camera { location <0.0 , .8 ,-3.0> look_at 0} light_source{< 3,3,-3> color rgb 1} sky_sphere { pigment{ gradient <0,1,0> color_map {[0 color rgb <.2,.1,0>][.5 color rgb 1]} scale 2}} plane {y,-2 pigment { hexagon color rgb .7 color rgb .5 color rgb .6 }} sphere { 0,1 texture { pigment{ color rgbft <.8,1,1,.4,.4> } finish { phong 1 reflection {0.40 metallic 0.5} } } interior { ior 1.5} } Yields this: ## Processing 3D rendering is built into Processing. void setup() { size(500, 500, P3D); } void draw() { background(192); translate(width/2, height/2); // optional color and lighting style stroke(200); fill(255); lights(); // draw sphere sphere(200); }  A sphere build from triangles (to for instance allow distortion) float rotX, rotY; PVector[][] sphere; int detail = 50; void setup() { size(600, 600, P3D); background(50, 50, 200); fill(255, 0, 200); stroke(0, 40); sphere = new PVector[detail+1][detail+1]; } void draw() { pointLight(255, 255, 255, -width, -height, 2*height); translate(width/2, height/2); rotateX(rotX); rotateY(rotY); float r = 200; for (int i = 0; i <= detail; i++) { float rows = map(i, 0, detail, 0, PI); for (int j = 0; j <= detail; j++) { float columns = map(j, 0, detail, 0, TWO_PI); float x = r * sin(rows) * cos(columns); float y = r * sin(rows) * sin(columns); float z = r * cos(rows); sphere[i][j] = new PVector(x, y, z); } } for (int i = 0; i < detail; i++) { beginShape(TRIANGLE_STRIP); for (int j = 0; j <= detail; j++) { PVector v1 = sphere[i][j]; vertex(v1.x, v1.y, v1.z); PVector v2 = sphere[i+1][j]; vertex(v2.x, v2.y, v2.z); } endShape(); } } void mouseDragged() { rotY -= (mouseX - pmouseX) * 0.01; rotX -= (mouseY - pmouseY) * 0.01; }  ## Python ### Ascii-Art Translation of: C import math shades = ('.',':','!','*','o','e','&','#','%','@') def normalize(v): len = math.sqrt(v[0]**2 + v[1]**2 + v[2]**2) return (v[0]/len, v[1]/len, v[2]/len) def dot(x,y): d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2] return -d if d < 0 else 0 def draw_sphere(r, k, ambient, light): for i in range(int(math.floor(-r)),int(math.ceil(r)+1)): x = i + 0.5 line = '' for j in range(int(math.floor(-2*r)),int(math.ceil(2*r)+1)): y = j/2 + 0.5 if x*x + y*y <= r*r: vec = normalize((x,y,math.sqrt(r*r - x*x - y*y))) b = dot(light,vec)**k + ambient intensity = int((1-b)*(len(shades)-1)) line += shades[intensity] if 0 <= intensity < len(shades) else shades[0] else: line += ' ' print(line) light = normalize((30,30,-50)) draw_sphere(20,4,0.1, light) draw_sphere(10,2,0.4, light)  Output:  &&&&&&&&&&###### &&eeeeeeeeeeeeeeee&&&&&&######%% &&oooo********ooooooeeeeee&&&&########%% oo****!!!!!!!!******ooooooeeee&&&&########%% eeoo**!!!!::::::::!!!!******ooooeeee&&&&########%%%% ee**!!::::::....::::::!!!!!!**ooooeeee&&&&&&########%%%% ee**!!::..............::::!!!!****ooooeeee&&&&########%%%%%% ee**!!::..................::::!!!!**ooooeeee&&&&##########%%%%%% oo!!::....................::::!!!!****ooeeee&&&&&&########%%%%%% oo**::......................::::!!!!****ooeeee&&&&&&##########%%%%%% &&**!!::......................::::!!!!****ooeeee&&&&&&##########%%%%%%%% oo**!!::......................::::!!!!**ooooeeee&&&&&&##########%%%%%%%% &&oo!!::........................::::!!****ooooeeee&&&&&&##########%%%%%%%%%% ee**!!::......................::::!!!!****ooooeeee&&&&&&##########%%%%%%%%%% ee**!!::::..................::::::!!!!****ooooeeee&&&&############%%%%%%%%%% ee**!!::::................::::::!!!!****ooooeeee&&&&&&############%%%%%%%%%% &&ee****!!::::............::::::!!!!****ooooooeeee&&&&&&##########%%%%%%%%%%%%%% &&eeoo**!!!!::::::::::::::::::!!!!******ooooeeee&&&&&&############%%%%%%%%%%%%%% &&eeoo****!!!!::::::::::::!!!!!!******ooooeeeeee&&&&&&############%%%%%%%%%%%%%% &&eeoooo**!!!!!!!!!!!!!!!!!!!!******ooooeeeeee&&&&&&############%%%%%%%%%%%%%%%% &&eeeeoo******!!!!!!!!!!********ooooooeeeeee&&&&&&&&############%%%%%%%%%%%%%%%% ##&&eeoooooo******************ooooooeeeeee&&&&&&&&############%%%%%%%%%%%%%%%%%% ##&&eeeeoooooooo******ooooooooooooeeeeee&&&&&&&&##############%%%%%%%%%%%%%%%%%% ##&&&&eeeeeeooooooooooooooooooeeeeeeee&&&&&&&&##############%%%%%%%%%%%%%%%%%%%% ##&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&&################%%%%%%%%%%%%%%%%%% ####&&&&&&eeeeeeeeeeeeeeeeee&&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%% ######&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&##################%%%%%%%%%%%%%%%%%%%%%% %%######&&&&&&&&&&&&&&&&&&&&&&&&####################%%%%%%%%%%%%%%%%%%%%%%%% ############&&&&&&&&&&&&########################%%%%%%%%%%%%%%%%%%%%%%%% %%############################################%%%%%%%%%%%%%%%%%%%%%%%%%% %%######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%##############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%% ::..::::!!** ..............::!!oo ..................::!!**ooee ......................::!!**ooee ......................::!!**ooee ........................::!!**ooooee ........................::!!**ooooee ::........................::!!**ooooeeee ........................::!!!!**ooooeeee ::......................::!!****ooeeeeee ::....................::!!!!**ooooeeeeee !!..................::!!!!****ooeeeeeeee **::::..........::::!!!!****ooooeeeeeeee !!!!::::::::::!!!!!!****ooooeeeeeeee oo**!!!!!!!!!!!!******ooooeeeeeeeeee oo**************ooooooeeeeeeeeee eeooooooooooooooooeeeeeeeeeeeeee eeeeooooooooeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeee eeeeeeeeeeee  ### Library: Pygame Renders a sphere with random Perlin noise. This code contains unnecessary functions which are part of a 3D graphics library I wrote. Uses Pygame and Python 3.2.2 import pygame from pygame.locals import * import time import sys import random import math  class Tricubic: def __init__(self,pts): self.coefficients = [] for plane in pts: planecoeffs = [] for line in plane: p = (line[3]-line[2])-(line[0]-line[1]) q = (line[0]-line[1])-p r = line[2]-line[0] s = line[1] planecoeffs.append([p,q,r,s]) self.coefficients.append(planecoeff) def Eval(at): return Misc.Cubic([CoeffBicubic(coeffs[0],d),CoeffBicubic(coeffs[1],d),CoeffBicubic(coeffs[2],d),CoeffBicubic(coeffs[3],d)],d.z) def CoeffCubic(coeffs,d): return (coeffs[0]*(d.x**3))+(coeffs[1]*(d.x**2))+(coeffs[2]*d.x)+coeffs[3] def CoeffBicubic(coeffs,d): return Misc.Cubic([CoeffCubic(coeffs[0],d),CoeffCubic(coeffs[1],d),CoeffCubic(coeffs[2],d),CoeffCubic(coeffs[3],d)],d.y) class Misc: def LinePara(line,t): return Vector3.Add(line[0],Vector3.Scale(Vector3.Subtract(line[1],line[0]),t)) def LUR(at,above): look = at.Unit() right = Vector3.Cross(look,above).Unit() up = Vector3.Scale(Vector3.Cross(look,right),-1) return [look,up,right] def LinePlane(line,triangle,cp=True): try: u = Vector3.Subtract(triangle.points[1].point,triangle.points[0]) v = Vector3.Subtract(triangle.points[2],triangle.points[0]) n = Vector3.Cross(u,v) r = (Vector3.Dot(n,Vector3.Subtract(triangle.points[0],line.start))/Vector3.Dot(n,line.direction)) if stp: point = Vector3.Add(Vector3.Scale(line.direction,r),line.start) w = Vector3.Subtract(point,triangle.points[0]) udv = Vector3.Dot(u,v) wdv = Vector3.Dot(w,v) vdv = Vector3.Dot(v,v) wdu = Vector3.Dot(w,u) udu = Vector3.Dot(u,u) denominator = (udv**2)-(udu*vdv) s = ((udv*wdv)-(vdv*wdu))/denominator t = ((udv*wdu)-(udu*wdv))/denominator return [r,Vector2(s,t),point] print('hooray') else: return [r] except: return None def Cubic(pts,d): p = (pts[3]-pts[2])-(pts[0]-pts[1]) q = (pts[0]-pts[1])-p r = pts[2]-pts[0] s = pts[1] return (p*(d**3))+(q*(d**2))+(r*d)+s def Bicubic(pts,d): return Misc.Cubic([Misc.Cubic(pts[0],d.x),Misc.Cubic(pts[1],d.x),Misc.Cubic(pts[2],d.x),Misc.Cubic(pts[3],d.x)],d.y) def Tricubic(pts,d): return Misc.Cubic([Misc.Bicubic(pts[0],d),Misc.Bicubic(pts[1],d),Misc.Bicubic(pts[2],d),Misc.Bicubic(pts[3],d)],d.z) def Quadcubic(pts,d): return Misc.Cubic([Misc.Tricubic(pts[0],d),Misc.Tricubic(pts[1],d),Misc.Tricubic(pts[2],d),Misc.Tricubic(pts[3],d)],d.w) def Linear(pts,d): return (pts[2]*d)+(pts[1]*(1-d)) def Bilinear(pts,d): return Misc.Linear([0,Misc.Linear(pts[1],d.x),Misc.Linear(pts[2],d.x)],d.y) def Trilinear(pts,d): return Misc.Linear([0,Misc.Bilinear(pts[1],d),Misc.Bilinear(pts[2],d)],d.z) def LP2(line,triangle,cp=True): try: bla = triangle.points[1] bla = triangle.points[0] u = Vector3.Subtract(triangle.points[1].point,triangle.points[0].point) v = Vector3.Subtract(triangle.points[2].point,triangle.points[0].point) n = Vector3.Cross(u,v) d = Vector3.Subtract(line[1],line[0]) r = (Vector3.Dot(n,Vector3.Subtract(triangle.points[0].point,line[0]))/Vector3.Dot(n,d)) if cp: point = Vector3.Add(Vector3.Scale(d,r),line[0]) w = Vector3.Subtract(point,triangle.points[0].point) udv = Vector3.Dot(u,v) wdv = Vector3.Dot(w,v) vdv = Vector3.Dot(v,v) wdu = Vector3.Dot(w,u) udu = Vector3.Dot(u,u) denominator = (udv**2)-(udu*vdv) s = ((udv*wdv)-(vdv*wdu))/denominator t = ((udv*wdu)-(udu*wdv))/denominator return (r,Vector2(s,t),point) else: return (r) except: return None def Phong(normal,viewer,light,material,term): # light (vector_to,diffuse,specular) # material (ambient,diffuse,specular,shininess) n = normal.Unit() v = viewer.Unit() l = light[0].Unit() ldn = Vector3.Dot(l,n) #print(ldn) val = 0 if ldn > 0: val += material[1][term]*ldn*light[1][term] rdv = Vector3.Dot(Vector3.Subtract(Vector3.Scale(n,2*ldn),l),v) if rdv > 0: val += (material[2][term]*(rdv**material[3])*light[2][term]) #print(val) return val def Lighting(ambient,normal,viewer,lights,material,term): # lights [(vector_to,diffuse,specular)] # material (ambient,diffuse,specular,shininess) val = material[0][term]*ambient[term] for light in lights: val += Misc.Phong(normal,viewer,light,material,term) return val def Lighting2(start,direction,ambient,intersect,triangle,lights): coord = intersect[1] val = Color.Add(Color.Multiply(ambient,Color.Multiply(triangle.material.color['ambient'],triangle.Map('ambient',coord))), Color.Multiply(triangle.material.color['glow'],triangle.Map('glow',coord))) for light in lights: for n in range(3): val[n] += Misc.Phong(triangle.InterpolatedNormal(coord), Vector3.Scale(direction,-1), (light.To(intersect[2]),light.Diffuse(intersect[2]),light.Specular(intersect[2])), (Color(), Color.Multiply(triangle.material.color['diffuse'],triangle.Map('diffuse',coord)), Color.Multiply(triangle.material.color['specular'],triangle.Map('specular',coord)), triangle.material.shiny),n) return val def Ray(start,direction,scene,color=True,sector=None): intersect = None intersected = None col = None for triangle in scene.triangles: possible = True if sector != None: possible = False for point in triangle.points: if not(point.sector.x < sector.x): possible = True if possible: possible = False for point in triangle.points: if not(point.sector.x > sector.x): possible = True if possible: possible = False for point in triangle.points: if not(point.sector.y < sector.y): possible = True if possible: possible = False for point in triangle.points: if not(point.sector.y > sector.y): possible = True possible = True if possible: tmp = Misc.LP2([start,Vector3.Add(start,direction)],triangle,color) write = False if type(tmp) == type(5.1): tmp = None if (tmp != None): if (intersect == None): if (tmp[0] > 0) and (tmp[1].x >= 0) and (tmp[1].y >= 0) and (tmp[1].x+tmp[1].y <= 1): write = True elif (tmp[0] > 0) and (tmp[0] < intersect[0]) and (tmp[1].x >= 0) and (tmp[1].y >= 0) and (tmp[1].x+tmp[1].y <= 1): write = True if write: intersect = tmp intersected = triangle if color and (intersect != None): applicable = [] for light in scene.lights: block = Misc.Ray(intersect[2],light.To(intersect[2]),scene,False) if block == None: applicable.append(light) elif light.location != None: if Vector3.Subtract(light.location,intersect[2]).Magnitude() < block[0]: applicable.append(light) col = Misc.Lighting2(start,direction,scene.ambient,intersect,intersected,applicable) return (intersect,col) else: return intersect class DirLight: def __init__(self,direction,diffuse,specular): self.location = None self.direction = direction.Unit() self.diffuse = diffuse self.specular = specular def To(self,frm): return Vector3.Scale(self.direction,-1) def Diffuse(self,to): return self.diffuse def Specular(self,to): return self.specular class Material: def __init__(self): self.color = {'ambient':Color(1,1,1), 'diffuse':Color(1,1,1), 'specular':Color(1,1,1), 'glow':Color(1,1,1)} self.maps = {'ambient':Map(), 'diffuse':Map(), 'specular':Map(), 'glow':Map(), 'bump':Map()} self.shiny = 10 class Map: def __init__(self,surface=None): self.surface = surface if self.surface != None: self.width = self.surface.get_width() self.height = self.surface.get_height() def __getitem__(self,index): if self.surface == None: return Color(1,1,1) else: try: return Color.From255(self.surface.get_at((int(index.x*(self.width-1)),int(index.y*(self.height-1))))) except: return Color(0,0,1) class Color: def __init__(self,r=0,g=0,b=0): self.r = r self.g = g self.b = b def __getitem__(self,index): if index == 0: return self.r elif index == 1: return self.g elif index == 2: return self.b def __setitem__(self,index,value): if index == 0: self.r = value elif index == 1: self.g = value elif index == 2: self.b = value def Multiply(A,B): return Color(A.r*B.r,A.g*B.g,A.b*B.b) def Add(A,B): return Color(A.r+B.r,A.g+B.g,A.b+B.b) def From255(A): return Color(A.r/255,A.g/255,A.b/255) class Vertex: def __init__(self,point,normal,maps): self.bpoint = point self.bnormal = normal self.maps = maps for name in ['ambient','diffuse','specular','glow','bump']: try: bla = self.maps[name] except: self.maps[name] = Vector2() self.sector = None def Transform(self,points,norms): self.point = Matrix2.Multiply(self.bpoint.Horizontal(),points).Vectorize() self.normal = Matrix2.Multiply(self.bnormal.Horizontal(),norms).Vectorize() class Triangle: def __init__(self,vertices,material=Material()): self.points = vertices self.material = material def Map(self,name,coord): pts = [] for n in range(3): pts.append(self.points[n].maps[name]) loc = Vector2.Add(pts[0], Vector2.Add(Vector2.Scale(Vector2.Subtract(pts[1],pts[0]),coord.x), Vector2.Scale(Vector2.Subtract(pts[2],pts[0]),coord.y))) #print(loc.x,loc.y) return self.material.maps[name][loc] def InterpolatedNormal(self,coord): return Vector3.Add(Vector3.Scale(self.points[0].normal,1-coord.x-coord.y), Vector3.Add(Vector3.Scale(self.points[1].normal,coord.x),Vector3.Scale(self.points[2].normal,coord.y))).Unit() class Line: def __init__(self,A,B=None,direction=None): self.start = A if B != None: self.direction = Vector3.Subtract(B,A).Unit() elif direction != None: self.direction = direction else: raise RuntimeError('Neither B nor direction are specified') class Scene: def __init__(self): self.triangles = [] self.vertices = [] self.lights = [] self.exterior = [] self.ambient = 0 class Matrix2: def __init__(self,data=[[]]): self.FromData(data) def __getitem__(self,index): return self.data[index[1]][index[0]] def __setitem__(self,index,value): self.data[index[1]][index[0]]=value def Dimension(self): self.rows = len(self.data) self.cols = len(self.data[0]) def FromData(self,data): self.data = data length=len(data[0]) for row in data: if len(row)!=length: self.data=None raise RuntimeError('Data rows are not of uniform length.') self.Dimension() def Multiply(A,B): if A.cols!=B.rows: raise RuntimeError('Column count of Matrix2 \"A\" does not match row count of Matrix2 \"B\".') matrix = Matrix2.Empty(B.cols,A.rows) x=0 while x<matrix.cols: y=0 while y<matrix.rows: val=0 n=0 while n<A.cols: val+=A[(n,y)]*B[(x,n)] n+=1 matrix[(x,y)]=val y+=1 x+=1 return matrix def Scalar(A,n): pass def Empty(rows,cols): data = [] row = [0]*rows n = 0 while n < cols: data.append(row[:]) n+=1 matrix=Matrix2(data) matrix.Dimension() return matrix def Identity(cols): matrix = Matrix2.Empty(cols,cols) n = 0 while n < cols: matrix[(n,n)]=1 n += 1 return matrix def Vectorize(self): if self.cols==1: if self.rows!=4: raise RuntimeError('Only 1 by 4 or 4 by 1 Matrix2s can be cast to Vector3s.') vertical=True elif self.rows==1: if self.cols!=4: raise RuntimeError('Only 1 by 4 or 4 by 1 Matrix2s can be cast to Vector3s.') vertical = False else: raise RuntimeError('Only 1 by 4 or 4 by 1 Matrix2s can be cast to Vector3s.') vector=[0]*4 n=0 while n<4: if vertical: vector[n]=self[(0,n)] else: vector[n]=self[(n,0)] n+=1 return Vector3(vector[0],vector[1],vector[2],vector[3]) def Print(self,decimals,spaces): length=0 for row in self.data: for val in row: string=str(round(val,decimals)) if length<len(string): length=len(string) text='' for row in self.data: temp='' for value in row: val=str(round(float(value),decimals)) pads=length-len(val) pad=int(pads/2) temp+=(' '*pad)+val+(' '*(pads-pad))+(' '*spaces) text+=(' '*spaces)+temp[0:len(temp)-1]+(' '*spaces)+'\n' return(text[0:len(text)-1]) def RotX(angle): return Matrix2([ [1,0,0,0], [0,math.cos(angle),0-math.sin(angle),0], [0,math.sin(angle),math.cos(angle),0], [0,0,0,1]]) def RotY(angle): return Matrix2([ [math.cos(angle),0,0-math.sin(angle),0], [0,1,0,0], [math.sin(angle),0,math.cos(angle),0], [0,0,0,1]]) def RotZ(angle): return Matrix2([ [math.cos(angle),0-math.sin(angle),0,0], [math.sin(angle),math.cos(angle),0,0], [0,0,1,0], [0,0,0,1]]) def Translate(vector): return Matrix2([ [1,0,0,0], [0,1,0,0], [0,0,1,0], [vector.x,vector.y,vector.z,1]]) def Scale(vector): return Matrix2([ [vector.x,0,0,0], [0,vector.y,0,0], [0,0,vector.z,0], [0,0,0,1]]) def Clone(self): data = [] for row in self.data: data.append(row[:]) return Matrix2(data) def Inverse(self): adjoint = self.Adjoint() det = self.Determinant() if det == 0: raise RuntimeError('Cannot find the inverse of a matrix with a determinant of 0') inverse = Matrix2.Empty(self.rows,self.cols) x = 0 while x < self.cols: y = 0 while y < self.rows: inverse[(x,y)] = adjoint[(x,y)]/det y += 1 x += 1 return inverse def Transpose(self): transpose = Matrix2.Empty(self.cols,self.rows) x = 0 while x < self.cols: y = 0 while y < self.rows: transpose[(y,x)] = self[(x,y)] y += 1 x += 1 return transpose def Adjoint(self): return self.Cofactors().Transpose() def Determinant(self): if self.rows != self.cols: raise RuntimeError('Cannot find the determinant of a non-square matrix') if self.rows == 1: return self[(0,0)] cofactors = self.Cofactors() determinant = 0 n = 0 while n < self.cols: determinant += self[(n,0)]*cofactors[(n,0)] n += 1 return determinant def Minors(self): if self.rows != self.cols: raise RuntimeError('Cannot find the minors of a non-square matrix') if self.rows == 1: raise RuntimeError('Cannot find the minors of a 1 by 1 matrix') minors = Matrix2.Empty(self.rows,self.cols) lines = range(self.rows) x = 0 while x < self.cols: y = 0 while y < self.cols: tiny = Matrix2.Empty(self.rows-1,self.cols-1) ox = 0 nx = 0 while ox < self.cols: oy = 0 ny = 0 while oy < self.cols: if not((ox == x) or (oy == y)): tiny[(nx,ny)] = self[(ox,oy)] if oy != y: ny += 1 oy += 1 if ox != x: nx += 1 ox += 1 minors[(x,y)] = tiny.Determinant() y += 1 x += 1 return minors def Cofactors(self): minors = self.Minors() cofactors = Matrix2.Empty(self.rows,self.cols) x = 0 while x < self.cols: y = 0 while y < self.rows: if int((x+y)/2) == ((x+y)/2): cofactors[(x,y)] = minors[(x,y)] else: cofactors[(x,y)] = -1*minors[(x,y)] y += 1 x += 1 return cofactors def Perspective(e): return Matrix2([ [1,0,0,0], [0,1,0,0], [0,0,1,1/e[2]], [-e[0],-e[1],0,0]]) def Add(A,B): if A.rows != B.rows: RuntimeError('The row counts of Matrix \"A\" and Matrix \"B\" are not identical.') if A.cols != B.cols: RuntimeError('The column counts of Matrix \"A\" and Matrix \"B\" are not identical.') matrix = Matrix.Empty(A.rows,A.cols) for x in range(A.cols): for y in range(A.rows): matrix[(x,y)] = A[(x,y)]+B[(x,y)] return matrix def Subtract(A,B): if A.rows != B.rows: RuntimeError('The row counts of Matrix \"A\" and Matrix \"B\" are not identical.') if A.cols != B.cols: RuntimeError('The column counts of Matrix \"A\" and Matrix \"B\" are not identical.') matrix = Matrix.Empty(A.rows,A.cols) for x in range(A.cols): for y in range(A.rows): matrix[(x,y)] = A[(x,y)]+B[(x,y)] return matrix def DivHomogeneous(self): if (self.cols,self.rows) == (1,4): for y in range(3): self[(0,y)] = self[(0,y)]/self[(0,3)] self[(0,3)] = 1 if (self.cols,self.rows) == (4,1): for x in range(3): self[(x,0)] = self[(x,0)]/self[(3,0)] self[(3,0)] = 1 else: raise RuntimeError('1 by 4 or 4 by 1 Matrix2 expected') def Object(pos,look,up,right): return Matrix2([ [right.x,right.y,right.z,0], [up.x,up.y,up.z,0], [look.x,look.y,look.z,0], [pos.x,pos.y,pos.z,1]]) def Camera(eye,look,up,right): return Matrix2([ [right.x,up.x,look.x,0], [right.y,up.y,look.y,0], [right.z,up.z,look.z,0], [-Vector3.Dot(eye,right), -Vector3.Dot(eye,up), -Vector3.Dot(eye,look),1]]) def YPR(rot): return Matrix2.Multiply( Matrix2.Multiply(Matrix2.RotZ(rot.z), Matrix2.RotX(rot.x)), Matrix2.RotY(rot.y)) class Vector2: def __init__(self,data=0,y=0): if (type(data) == type(5)) or (type(data) == type(5.1)): self.x = data self.y = y else: self.x = data[0] self.y = data[1] def __getitem__(self,index): if index == 0: return self.x elif index == 1: return self.y def __setitem__(self,index,value): if index == 0: self.x = value elif index == 1: self.y = 1 def Add(A,B): return Vector2(A.x+B.x,A.y+B.y) def Subtract(A,B): return Vector2(A.x-B.x,A.y-B.y) def Scale(A,n): return Vector2(A.x*n,A.y*n) def Magnitude(self): return ((self.x**2)+(self.y**2))**.5 def Unit(self): return Vector2.Scale(self,1/self.Magnitude()) def Clone(self): return Vector2(self.x,self.y) class Vector3: def __init__(self,data=0,y=0,z=0,w=1): if (type(data) == type(5)) or (type(data) == type(5.1)): self.x = data/w self.y = y/w self.z = z/w else: try: temp = data[3] except: temp = 1 self.x = data[0]/temp self.y = data[1]/temp self.z = data[2]/temp def __getitem__(self,index): if index == 0: return self.x elif index == 1: return self.y elif index == 2: return self.z def __setitem__(self,index,value): if index == 0: self.x = value elif index == 1: self.y = value elif index == 2: self.z = value def Vertical(self): return Matrix2([[self.x],[self.y],[self.z],[1]]) def Horizontal(self): return Matrix2([[self.x,self.y,self.z,1]]) def Dot(A,B): return (A.x*B.x)+(A.y*B.y)+(A.z*B.z) def Cross(A,B): return Vector3([ (A.y*B.z)-(A.z*B.y), (A.z*B.x)-(A.x*B.z), (A.x*B.y)-(A.y*B.x)]) def Add(A,B): return Vector3(A.x+B.x,A.y+B.y,A.z+B.z) def Subtract(A,B): return Vector3(A.x-B.x,A.y-B.y,A.z-B.z) def Scale(A,n): return Vector3(A.x*n,A.y*n,A.z*n) def Magnitude(self): return ((self.x**2)+(self.y**2)+(self.z**2))**.5 def Print(self,decimals,spaces): return self.Horizontal().Print(decimals,spaces) def Same(A,B): same = False if A.x == B.x: if A.y == B.y: if A.z == B.z: same = True return same def Unit(self): return Vector3.Scale(self,1/self.Magnitude()) def Clone(self): return Vector3(self.x,self.y,self.z) class Vector4: def __init__(self,data=0,y=0,z=0,w=0): if (type(data) == type(5)) or (type(data) == type(5.1)): self.x = data self.y = y self.z = z self.w = w else: self.x = data[0] self.y = data[0] self.z = data[0] self.w = data[0] points = [Vector3([-1,-1,0]),Vector3([1,-1,0]),Vector3([0,1,0])] width = 255 height = width screen = pygame.display.set_mode((width,height),0,32) scl = 2 pos = Vector3([0,0,5]) view = Vector3([0,0,1]) frames = 0 def Transform(point,mat): return Matrix2.Multiply(point.Horizontal(),mat).Vectorize() def RV(): return Vector3([random.random(),random.random(),random.random()]) green = pygame.Color(0,255,0) def XY(bla): return (((width*bla[0])+width)/2,((height*bla[1])+width)/2) screen.fill(pygame.Color(0,0,0)) size = 255 world = Matrix2.Identity(4) inv = world.Inverse() invt = world.Inverse().Transpose() center = Vector3(0,0,2) def Texture(size): texture = [] for pa in range(size): plane = [] for pb in range(size): line = [] for pc in range(size): line.append(random.random()) plane.append(line) texture.append(plane) return texture lights = [(Vector3(-10,6,-9),[.7,.7*.9,.7*.8],[.7,.7*.9,.9*.8])] lights = [(Vector3(-10,6,-9),[.8,.8,.8],[.7,.7,.7])] depth = 3 groups = [] for n in range(1): textures = [] for n in range(depth): textures.append(Texture(4**(n+1))) groups.append(textures) def Select(texture,at): sel = [] for pa in range(4): aplane = texture[pa+math.floor(at.z)] bplane = [] for pb in range(4): aline = aplane[pb+math.floor(at.y)] bline = [] for pc in range(4): bline.append(aline[pc+math.floor(at.x)]) bplane.append(bline) sel.append(bplane) return (sel,Vector3(at.x%1,at.y%1,at.z%1)) def Round(val): return val-(val-math.floor(val)) theta = math.tan(70*math.pi/360) for x in range(width): for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() if event.type == KEYDOWN: pass for y in range(height): l = Vector3(theta*2*((x/width)-.5),theta*2*((y/width)-.5),1).Unit() ldc = Vector3.Dot(l,center) d = ldc-(((ldc**2)-Vector3.Dot(center,center)+1)**.5) if type(d) != type((-1)**.5): intersection = Vector3.Scale(l,d) normal = Vector3.Subtract(intersection,center).Unit() point = Transform(normal,world) s = Vector3.Scale(Vector3.Add(point,Vector3(1,1,1)),.5) val = 0 for i in range(depth): sel = Select(groups[0][i],Vector3.Scale(s,4**i)) val += Misc.Tricubic(sel[0],sel[1])*((1/2)**i)/4 val = (25*val)%1 vals = [0,Misc.Linear([0,.3,1],val),1] coloring = [] for i in range(3): #light = Misc.Lighting([1,1,1],normal,Vector3.Scale(intersection,-1),lights,([0,.03*val,.03],[0,.7*val,.7],[.3,.3,.3],7),i) light = Misc.Lighting([.1,.1,.1],normal,Vector3.Scale(intersection,-1),lights,(vals,vals,[1,1,1],10),i) if light > 1: light = 1 elif light < 0: light = 0 coloring.append(round(255*light)) screen.set_at((x,height-y),pygame.Color(coloring[0],coloring[1],coloring[2])) pygame.display.update() pygame.image.save(screen,"PythonSphere.png") while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() if event.type == KEYDOWN: pass  ### Library: VPython Works with: Python version 2.7.5 Short version: from visual import * scene.title = "VPython: Draw a sphere" sphere() # using defaults, see http://www.vpython.org/contents/docs/defaults.html  Regular version, with some window-dressing: from __future__ import print_function, division from visual import * title = "VPython: Draw a sphere" scene.title = title print( "%s\n" % title ) print( 'Drag with right mousebutton to rotate view' ) print( 'Drag up+down with middle mousebutton to zoom') scene.autocenter = True # uncomment any (or all) of those variants: S1 = sphere(pos=(0.0, 0.0, 0.0), radius=1.0, color=color.blue) #S2 = sphere(pos=(2.0, 0.0, 0.0), radius=1.0, material=materials.earth) #S3 = sphere(pos=(0.0, 2.0, 0.0), radius=1.0, material=materials.BlueMarble) #S4 = sphere(pos=(0.0, 0.0, 2.0), radius=1.0, # color=color.orange, material=materials.marble) while True: # Animation-loop rate(100) pass # no animation in this demo  ## Racket Using the Typed Racket language with the plot library: #lang typed/racket (require plot/typed) (plot3d (polar3d (λ (θ ρ) 1)) #:altitude 25)  ## Raku (formerly Perl 6) ### Pure Raku Translation of: C The C code is modified to output a .pgm file. Works with: Rakudo version 2018.10 my$width = my $height = 255; # must be odd my @light = normalize([ 3, 2, -5 ]); my$depth = 255;

sub MAIN ($outfile = 'sphere-perl6.pgm') { spurt$outfile, "P5\n$width$height\n$depth\n"; # .pgm header my$out = open( $outfile, :a, :bin ) orelse .die;$out.write( Blob.new(draw_sphere( ($width-1)/2, .9, .2) ) );$out.close;
}

sub normalize (@vec) { @vec »/» ([+] @vec »*« @vec).sqrt }

sub dot (@x, @y) { -([+] @x »*« @y) max 0 }

sub draw_sphere ( $rad,$k, $ambient ) { my @pixels[$height];
my $r2 =$rad * $rad; my @range = -$rad .. $rad; @range.hyper.map: ->$x {
my @row[$width]; @range.map: ->$y {
if (my $x2 =$x * $x) + (my$y2 = $y *$y) < $r2 { my @vector = normalize([$x, $y, ($r2 - $x2 -$y2).sqrt]);
my $intensity = dot(@light, @vector) **$k + $ambient; my$pixel = (0 max ($intensity *$depth).Int) min $depth; @row[$y+$rad] =$pixel;
}
else {
@row[$y+$rad] = 0;
}
}
@pixels[$x+$rad] = @row;
}
flat |@pixels.map: *.list;
}


### Cairo graphics library

use Cairo;

given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
given Cairo::Context.new($_) { my Cairo::Pattern::Solid$bg .= create(.5,.5,.5);
.rectangle(0, 0, 256, 256);
.pattern($bg); .fill;$bg.destroy;

my Cairo::Pattern::Gradient::Radial $shadow .= create(105.2, 102.4, 15.6, 102.4, 102.4, 128.0);$shadow.add_color_stop_rgba(0, .3, .3, .3, .3);
$shadow.add_color_stop_rgba(1, .1, .1, .1, .02); .pattern($shadow);
.arc(136.0, 134.0, 110, 0, 2 * pi);
.fill;
$shadow.destroy; my Cairo::Pattern::Gradient::Radial$sphere .=
create(115.2, 102.4, 25.6, 102.4,  102.4, 128.0);
$sphere.add_color_stop_rgba(0, 1, 1, .698, 1);$sphere.add_color_stop_rgba(1, .923, .669, .144, 1);
.pattern($sphere); .arc(128.0, 128.0, 110, 0, 2 * pi); .fill;$sphere.destroy;
};
.write_png('sphere2-perl6.png');
}


See sphere2-perl6.png (offsite .png image)

## REXX

This program is modeled after the   C   version.

The REXX language doesn't have a   SQRT   function, so a version is included here.
Same with the   CEILing   and   FLOOR   functions.

Programming note:   the output will appear slightly different when executed on an EBCDIC machine   (due to different dithering characters).

/*REXX program expresses a  lighted sphere  with  simple characters  used for shading.  */
call drawSphere  19,  4,   2/10,  '30 30 -50'    /*draw a sphere with a radius of  19.  */
call drawSphere  10,  2,   4/10,  '30 30 -50'    /*  "  "    "     "  "    "    "  ten. */
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
ceil:  procedure;   parse arg x;  _= trunc(x);                    return _ +(x>0) * (x\=_)
floor: procedure;   parse arg x;  _= trunc(x);                    return _ -(x<0) * (x\=_)
norm:  parse arg $a$b $c; _= sqrt($a**2 + $b**2 +$c**2); return  $a/_$b/_  $c/_ /*──────────────────────────────────────────────────────────────────────────────────────*/ drawSphere: procedure; parse arg r, k, ambient, lightSource /*obtain the four arguments*/ if 8=='f8'x then shading= ".:!*oe&#%@" /* EBCDIC dithering chars. */ else shading= "·:!°oe@░▒▓" /* ASCII " " */ parse value norm(lightSource) with s1 s2 s3 /*normalize light source. */ shadeLen= length(shading) - 1; rr= r**2; r2= r+r /*handy─dandy variables. */ do i=floor(-r ) to ceil(r ); x= i + .5; xx= x**2;$=
do j=floor(-r2)  to ceil(r2);   y= j * .5  + .5;       yy= y**2;       z= xx+yy
if z<=rr  then do                                 /*is point within sphere ? */
parse value  norm(x  y  sqrt(rr - xx - yy) )   with   v1  v2  v3
dot= min(0, s1*v1 + s2*v2 + s3*v3) /*the dot product of above.*/
b= -dot**k  +  ambient             /*calculate the brightness.*/
else brite= max(0,  (1-b) * shadeLen)  % 1
$=$ || substr(shading, brite + 1,  1)
end                                /* [↑]  build display line.*/
else $=$' '                            /*append a blank to line.  */
end   /*j*/                                       /*[↓] strip trailing blanks*/
say strip($, 'T') /*show a line of the sphere*/ end /*i*/ /* [↑] display the sphere.*/ return /*──────────────────────────────────────────────────────────────────────────────────────*/ sqrt: procedure; parse arg x; if x=0 then return 0; d= digits(); numeric digits; h= d+6 numeric form; m.=9; parse value format(x,2,1,,0) 'E0' with g "E" _ .; g= g*.5'e'_%2 do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/ do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/; return g  output when using the default input and executed on an ASCII machine: (Shown at 1/2 size.)  eeeeeeeeee@@@@@@@ eoooooooooooooooeeeee@@@@@@@░ oo°°°!!!!!!!!°°°°°°ooooeeeee@@@@@@@░░ o°°!!!:::::::::!!!!!°°°°°ooooeeee@@@@@@@░░░ o°!!::::·········:::::!!!!°°°ooooeeeee@@@@@@@░░░░ o°!:::················::::!!!°°°°oooeeeee@@@@@@@░░░░░ o°!::····················::::!!!°°°°oooeeeee@@@@@@@░░░░░░ o°!::·······················:::!!!!°°°ooooeeee@@@@@@@@░░░░░░░ o°!::·························:::!!!°°°ooooeeeee@@@@@@@░░░░░░░░ o°!:···························:::!!!°°°°oooeeeee@@@@@@@@░░░░░░░░ o°!::··························::::!!!°°°ooooeeeee@@@@@@@@░░░░░░░░░ o°!::···························:::!!!!°°°ooooeeeee@@@@@@@@░░░░░░░░░░ o°!!::··························::::!!!°°°°ooooeeeee@@@@@@@@░░░░░░░░░░░ eo°!!::·························::::!!!°°°°ooooeeeee@@@@@@@@@░░░░░░░░░░░░ oo°!!::························::::!!!°°°°ooooeeeeee@@@@@@@@░░░░░░░░░░░░░ eoo°!!:::·····················::::!!!!°°°°oooooeeeee@@@@@@@@@░░░░░░░░░░░░░░ eoo°°!!:::·················:::::!!!!!°°°°ooooeeeeee@@@@@@@@@░░░░░░░░░░░░░░░ eoo°°!!!:::::··········:::::::!!!!!°°°°oooooeeeeee@@@@@@@@@@░░░░░░░░░░░░░░░ eeoo°°°!!!:::::::::::::::::!!!!!!°°°°°oooooeeeeee@@@@@@@@@@░░░░░░░░░░░░░░░░ eeooo°°°!!!!!!!:::::::!!!!!!!!°°°°°°oooooeeeeee@@@@@@@@@@@░░░░░░░░░░░░░░░░░ @eeooo°°°°°!!!!!!!!!!!!!!!°°°°°°°ooooooeeeeeee@@@@@@@@@@@░░░░░░░░░░░░░░░░░░ @@eeeoooo°°°°°°°°°°°°°°°°°°°°°oooooooeeeeeee@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░ @@@eeeoooooo°°°°°°°°°°°°°oooooooooeeeeeeee@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░ @@@eeeeeooooooooooooooooooooooeeeeeeeee@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░ @@@@@eeeeeeeooooooooooooeeeeeeeeeeee@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░ @@@@@@eeeeeeeeeeeeeeeeeeeeeeeee@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░ @@@@@@@@@eeeeeeeeeeeeeeeee@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░ ░@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░@@@@@@@@@@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░ ::···:::!!!°o ··············::!!°oo ··················::!!°°ooe ·····················::!!°°ooee ·······················::!!°°ooee ························::!!°°oooee ·························::!!°°oooeee :························::!!!°°oooeeee ························::!!!°°ooooeeee :······················::!!!°°°oooeeeee :····················:::!!!°°°oooeeeeee !:·················:::!!!°°°°oooeeeeeee °!:::···········::::!!!!°°°ooooeeeeeeee °!!!:::::::::::!!!!!°°°°oooooeeeeeeee o°°!!!!!!!!!!!!!°°°°°oooooeeeeeeeee oo°°°°°°°°°°°°°°ooooooeeeeeeeeeee eoooooooooooooooooeeeeeeeeeeeee eeeooooooooeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeee  ## Ruby Library: Shoes Shoes comes with this sample program. Shoes.app :width => 500, :height => 500, :resizable => false do image 400, 470, :top => 30, :left => 50 do nostroke fill "#127" image :top => 230, :left => 0 do oval 70, 130, 260, 40 blur 30 end oval 10, 10, 380, 380 image :top => 0, :left => 0 do fill "#46D" oval 30, 30, 338, 338 blur 10 end fill gradient(rgb(1.0, 1.0, 1.0, 0.7), rgb(1.0, 1.0, 1.0, 0.0)) oval 80, 14, 240, 176 image :top => 0, :left => 0 do fill "#79F" oval 134, 134, 130, 130 blur 40 end image :top => 150, :left => 40, :width => 320, :height => 260 do fill gradient(rgb(0.7, 0.9, 1.0, 0.0), rgb(0.7, 0.9, 1.0, 0.6)) oval 60, 60, 200, 136 blur 20 end end end  ## Rust Translation of: Go // [dependencies] // image = "0.23" use image::{GrayImage, Luma}; type Vector = [f64; 3]; fn normalize(v: &mut Vector) { let inv_len = 1.0/dot_product(v, v).sqrt(); v[0] *= inv_len; v[1] *= inv_len; v[2] *= inv_len; } fn dot_product(v1: &Vector, v2: &Vector) -> f64 { v1.iter().zip(v2.iter()).map(|(x, y)| *x * *y).sum() } fn draw_sphere(radius: u32, k: f64, ambient: f64, dir: &Vector) -> GrayImage { let width = radius * 4; let height = radius * 3; let mut image = GrayImage::new(width, height); let mut vec = [0.0; 3]; let diameter = radius * 2; let r = radius as f64; let xoffset = (width - diameter)/2; let yoffset = (height - diameter)/2; for i in 0..diameter { let x = i as f64 - r; for j in 0..diameter { let y = j as f64 - r; let z = r * r - x * x - y * y; if z >= 0.0 { vec[0] = x; vec[1] = y; vec[2] = z.sqrt(); normalize(&mut vec); let mut s = dot_product(&dir, &vec); if s < 0.0 { s = 0.0; } let mut lum = 255.0 * (s.powf(k) + ambient)/(1.0 + ambient); if lum < 0.0 { lum = 0.0; } else if lum > 255.0 { lum = 255.0; } image.put_pixel(i + xoffset, j + yoffset, Luma([lum as u8])); } } } image } fn main() { let mut dir = [-30.0, -30.0, 50.0]; normalize(&mut dir); match draw_sphere(200, 1.5, 0.2, &dir).save("sphere.png") { Ok(()) => {} Err(error) => eprintln!("{}", error), } }  Output: ## Scala object Sphere extends App { private val (shades, light) = (Seq('.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@'), Array(30d, 30d, -50d)) private def drawSphere(r: Double, k: Double, ambient: Double): Unit = { def dot(x: Array[Double], y: Array[Double]) = { val d = x.head * y.head + x(1) * y(1) + x.last * y.last if (d < 0) -d else 0D } for (i <- math.floor(-r).toInt to math.ceil(r).toInt; x = i + .5) println( (for (j <- math.floor(-2 * r).toInt to math.ceil(2 * r).toInt; y = j / 2.0 + .5) yield if (x * x + y * y <= r * r) { def intensity(vec: Array[Double]) = { val b = math.pow(dot(light, vec), k) + ambient if (b <= 0) shades.length - 2 else math.max((1 - b) * (shades.length - 1), 0).toInt } shades(intensity(normalize(Array(x, y, scala.math.sqrt(r * r - x * x - y * y))))) } else ' ').mkString) } private def normalize(v: Array[Double]): Array[Double] = { val len = math.sqrt(v.head * v.head + v(1) * v(1) + v.last * v.last) v.map(_ / len) } normalize(light).copyToArray(light) drawSphere(20, 4, .1) drawSphere(10, 2, .4) }  Output: See it in running in your browser by ScalaFiddle (JavaScript) or by Scastie (JVM). ## Sidef Translation of: Raku Produces a PGM image. func normalize (vec) { vec »/» (vec »*« vec -> sum.sqrt) } func dot (x, y) { -(x »*« y -> sum) max 0 } var x = var y = 255 x += 1 if x.is_even # must be odd var light = normalize([ 3, 2, -5 ]) var depth = 255 func draw_sphere(rad, k, ambient) { var pixels = [] var r2 = (rad * rad) var range = (-rad .. rad) for x,y in (range ~X range) { if ((var x2 = x*x) + (var y2 = y*y) < r2) { var vector = normalize([x, y, (r2 - x2 - y2).sqrt]) var intensity = (dot(light, vector)**k + ambient) var pixel = (0 max (intensity*depth -> int) min depth) pixels << pixel } else { pixels << 0 } } return pixels } var outfile = %f'sphere-sidef.pgm' var out = outfile.open('>:raw') out.say("P5\n#{x} #{y}\n#{depth}") # .pgm header out.print(draw_sphere((x-1)/2, .9, .2).map{.chr}.join) out.close  ## Smalltalk there are various OpenGL bindings available; here is a translation of the bare-bones code from C/Go: Works with: Smalltalk/X although there is a Point3 class in some loadable library, here is some self contained code, defining a local anon Point3D class. Point3D := Point subclass:#Point3D instanceVariableNames:'z' classVariableNames:'' poolDictionaries:'' category:'' inEnvironment:nil. Point3D compile:'z ^ z'. Point3D compile:'z:v z := v'. normalize := [:v | |invLen| invLen := 1 / (dot value:v value:v) sqrt. v x: v x * invLen. v y: v y * invLen. v z: v z * invLen. ]. dot := [:a :b | (a x * b x) + (a y * b y) + (a z * b z) ]. drawSphere := [:r :k :amb :dir | |w h imh vec img| w := r*4. h := r*3. img := Image width:w height:h depth:8. img photometric:#blackIs0; createPixelStore. vec := Point3D new. 0-r to:r do:[:x | 0-r to:r do:[:y | |z s lum| (z := (r*r) - (x*x) - (y*y)) >= 0 ifTrue:[ vec x: x. vec y: y. vec z: z sqrt. normalize value:vec. s := dot value:dir value:vec. s < 0 ifTrue:[ s := 0 ]. lum := 255 * ((s raisedTo: k) + amb) / (1 + amb). lum < 0 ifTrue:[ lum := 0 ] ifFalse:[ lum > 255 ifTrue:[ lum := 255 ]]. img atX:(x+(w//2)) y:(y+(h//2)) put:(Color greyByte:lum). ] ] ]. img ]. main := [ |dir img| dir := Point3D new x:-30; y:-30; z:50; yourself. normalize value:dir. img := drawSphere value: 100 value: 1.5 value: 0.2 value: dir. img displayOn:(View new extent:400@400; openAndWait). img saveOn:'sphere.png'. ]. main value.  ## SVG Not quite a sphere. ## Swift In Playground for example: class Sphere: UIView{ override func drawRect(rect: CGRect) { let context = UIGraphicsGetCurrentContext() let locations: [CGFloat] = [0.0, 1.0] let colors = [UIColor.whiteColor().CGColor, UIColor.blueColor().CGColor] let colorspace = CGColorSpaceCreateDeviceRGB() let gradient = CGGradientCreateWithColors(colorspace, colors, locations) var startPoint = CGPoint() var endPoint = CGPoint() startPoint.x = self.center.x - (self.frame.width * 0.1) startPoint.y = self.center.y - (self.frame.width * 0.15) endPoint.x = self.center.x endPoint.y = self.center.y let startRadius: CGFloat = 0 let endRadius: CGFloat = self.frame.width * 0.38 CGContextDrawRadialGradient (context, gradient, startPoint, startRadius, endPoint, endRadius, 0) } } var s = Sphere(frame: CGRectMake(0, 0, 200, 200))  In SwiftUI: struct ContentView: View { var body: some View { let gradient = RadialGradient(gradient: Gradient(colors:[.white, .black]), center: .init(x: 0.4, y: 0.4), startRadius: 10, endRadius: 100) return Circle() .fill(gradient) .frame(width: 200, height: 200) } }  ## Tcl Library: Tk Assuming the task is to draw a likeness of a sphere, this would usually do: proc grey {n} {format "#%2.2x%2.2x%2.2x"$n $n$n}

pack [canvas .c -height 400 -width 640 -background white]

for {set i 0} {$i < 255} {incr i} { set h [grey$i]
.c create arc [expr {100+$i/5}] [expr {50+$i/5}] [expr {400-$i/1.5}] [expr {350-$i/1.5}] \
-start 0 -extent 359 -fill $h -outline$h
}


Results in this image:

## LaTeX

Library: PGF

The PGF shadings library includes a "ball" for a 3-D style highlight.

\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\end{tikzpicture}
\end{document}


## Turing

Translated and optimized from the Algol W solution and others posted here.

% Draw a sphere in ASCII art in Turing

% Light intensity to character map

% Absolute dot product of x and y
function dot (x, y : array 1 .. 3 of real) : real
result abs (x(1) * y(1) + x(2) * y(2) + x(3) * y(3))
end dot

% Vector normalization
procedure normalize (var v : array 1 .. 3 of real)
const norm := sqrt (v(1)**2 + v(2)**2 + v(3)**2)
for i : 1 .. 3
v(i) := v(i) / norm
end for
end normalize

% Draws a sphere using ASCII art
procedure drawSphere (radius : real, k : int, lightsource : array 1 .. 3 of real, brightness : real)
const diameter := 2.0 * radius
var x := i + 0.5
for j : floor (-diameter) .. ceil (diameter)
var y  := j / 2 + 0.5

if x**2 + y**2 <= radius**2 then
var vec : array 1 .. 3 of real
vec(1) := x; vec(2) := y; vec(3) := sqrt (radius**2 - x**2 - y**2)
normalize (vec)

const b := dot (lightsource, vec) ** k + brightness
var intensity := round ((1 - b) * maxShades)

if intensity < 1 then
intensity := 1
end if

else
put ' ' ..
end if
end for
put ""
end for
end drawSphere

% Light source
var lightsource : array 1 .. 3 of real := init (30, 30, -59)
normalize (lightsource)
const brightness := 0.1

% Draw some spheres
drawSphere (20, 4, lightsource, brightness)
drawSphere (15, 10, lightsource, brightness)
Output:
                               ###############%%
#&&&eeeeeeeeee&&&&&&#######%%%%
&&eeeoooooooooooooeeeee&&&&&######%%%%%
&eeooo**************oooooeeee&&&&&#####%%%%%%
&eoo***!!!!!!!!!!!!!!!*****ooooeee&&&&&#####%%%%%%%
&eo**!!!:::::::::::::::!!!!****oooeeee&&&&######%%%%%%%
&eo**!!:::.............::::!!!!***ooooeee&&&&######%%%%%%%%
&eo**!!::..................::::!!!***ooooeee&&&&######%%%%%%%%%
&oo*!!::.....................::::!!!***oooeeee&&&&#####%%%%%%%%%%
#eo**!::........................:::!!!!***oooeee&&&&######%%%%%%%%%%%
&eo**!::.........................::::!!!***oooeeee&&&&#####%%%%%%%%%%%%
&eoo*!!::.........................::::!!!***oooeeee&&&&######%%%%%%%%%%%%
#&eo*!!::..........................:::!!!!***oooeeee&&&&######%%%%%%%%%%%%%
&eo**!!::.........................::::!!!***ooooeee&&&&&######%%%%%%%%%%%%%
&eeo**!!::.........................:::!!!****oooeeee&&&&#######%%%%%%%%%%%%%%
&eeo**!!::.......................::::!!!!***ooooeee&&&&&######%%%%%%%%%%%%%%%
#&eeo**!!:::.....................::::!!!****ooooeeee&&&&#######%%%%%%%%%%%%%%%%
#&eeoo**!!::::................:::::!!!!****ooooeeee&&&&&######%%%%%%%%%%%%%%%%%
#&eeoo***!!!:::::.........:::::::!!!!****oooooeeee&&&&&#######%%%%%%%%%%%%%%%%%
#&&eeoo***!!!!::::::::::::::::!!!!!*****ooooeeeee&&&&&#######%%%%%%%%%%%%%%%%%%
#&&eeeoo****!!!!!!!:::::!!!!!!!!******ooooeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%
##&&eeeooo*****!!!!!!!!!!!!!*******oooooeeeeee&&&&&########%%%%%%%%%%%%%%%%%%%%
###&&eeeooooo*******************ooooooeeeeee&&&&&&########%%%%%%%%%%%%%%%%%%%%%
%##&&&&eeeeooooooo********oooooooooeeeeee&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%
####&&&&eeeeeoooooooooooooooooeeeeeeee&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%
%####&&&&&eeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%
%#####&&&&&&&&eeeeeeeeeeeeee&&&&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%######&&&&&&&&&&&&&&&&&&&&&&&&&&############%%%%%%%%%%%%%%%%%%%%%%%%%%%#
%%%%########&&&&&&&&&&&&&&&&&###############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%##################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
%%%%%%%############################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
%%%%%%%%%%#################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%
%%%%########%%%%%%%%%%%%%%%
%####&&&&&&&&#######%%%%%%%%%%%%%
%###&&eeeeooeeeee&&&#####%%%%%%%%%%%%%%
%##&eeoo********oooee&&&####%%%%%%%%%%%%%%%
%##&eo**!!::::::!!!**ooee&&#####%%%%%%%%%%%%%%%
%#&eo**!:.........::!**ooee&&####%%%%%%%%%%%%%%%%
##&eo*!:............:!!*ooee&&&####%%%%%%%%%%%%%%%%
%%#&eo*!:.............:!!**oee&&&####%%%%%%%%%%%%%%%%%%
%#&&eo*!:............::!!*ooee&&#####%%%%%%%%%%%%%%%%%%
%##&eoo*!:...........::!!**oee&&&####%%%%%%%%%%%%%%%%%%%%
%%##&eeo*!!:........:::!!*ooeee&&#####%%%%%%%%%%%%%%%%%%%%%
%%##&&eoo*!!::::::::!!!**ooee&&&#####%%%%%%%%%%%%%%%%%%%%%%
%%###&eeoo***!!!!!!***oooeee&&&#####%%%%%%%%%%%%%%%%%%%%%%%
%%%##&&&eeooooo**oooooeeee&&&######%%%%%%%%%%%%%%%%%%%%%%%%
%%%####&&&eeeeeeeeeeeee&&&&######%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%#####&&&&&&&&&&&&&&&#######%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%########&&&&###########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%#####%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%


## VBScript

Translation of: C
shades = Array(".", ":", "!", "*", "o", "e", "&", "#", "%", "@")
light = Array(30, 30, -50)

Sub Normalize(v)
length = Sqr(v(0)*v(0) + v(1)*v(1) + v(2)*v(2))
v(0) = v(0)/length : v(1) = v(1)/length : v(2) = v(2)/length
End Sub

Function Dot(x, y)
d = x(0)*y(0) + x(1)*y(1) + x(2)*y(2)
If d < 0 Then Dot = -d Else Dot = 0 End If
End Function

'floor function is the Int function
'ceil function implementation
Function Ceil(x)
Ceil = Int(x)
If Ceil <> x Then Ceil = Ceil + 1 End if
End Function

Sub DrawSphere(R, k, ambient)
Dim i, j, intensity, inten, b, x, y
Dim vec(3)
For i = Int(-R) to Ceil(R)
x = i + 0.5
line = ""
For j = Int(-2*R) to Ceil(2*R)
y = j / 2 + 0.5
If x * x + y * y <= R*R Then
vec(0) = x
vec(1) = y
vec(2) = Sqr(R * R - x * x - y * y)
Normalize vec
b = dot(light, vec)^k + ambient
intensity = Int((1 - b) * UBound(shades))
If intensity < 0 Then intensity = 0 End If
End If
Else
line = line & " "
End If
Next
WScript.StdOut.WriteLine line
Next
End Sub

Normalize light
DrawSphere 20, 4, 0.1
DrawSphere 10,2,0.4
Output:
                               &&&&&&&&&&#######
&eeeeeeeeeeeeeeee&&&&&&#######%
&eoooo*******oooooooeeeee&&&&&########%
eoo****!!!!!!!!******oooooeeee&&&&&########%%
eoo**!!!!::::::::!!!!!*****ooooeeee&&&&&########%%%
eo**!!::::::...:::::::!!!!!***ooooeeee&&&&&########%%%%
eo*!!:::.............:::::!!!!***ooooeeee&&&&&########%%%%%
eo*!!:::.................::::!!!!***ooooeeee&&&&#########%%%%%%
eo*!!::....................::::!!!****oooeeee&&&&&#########%%%%%%
&o**!::......................::::!!!****oooeeee&&&&&##########%%%%%%%
&o**!::.......................::::!!!****oooeeee&&&&&##########%%%%%%%%
&oo*!!::.......................:::!!!!***ooooeeee&&&&&##########%%%%%%%%%
&eo*!!::.......................::::!!!****ooooeeee&&&&&##########%%%%%%%%%%
eo**!!::......................::::!!!!***ooooeeeee&&&&&##########%%%%%%%%%%
&eo**!!:::...................:::::!!!!****ooooeeee&&&&&###########%%%%%%%%%%%
eeo**!!::::................:::::!!!!!****ooooeeee&&&&&&###########%%%%%%%%%%%
&eeo***!!:::::...........::::::!!!!!****oooooeeee&&&&&&###########%%%%%%%%%%%%%
&eeoo**!!!!::::::::::::::::::!!!!!*****ooooeeeee&&&&&&############%%%%%%%%%%%%%
&eeooo***!!!!::::::::::::!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%%
&&eeooo***!!!!!!!!!!!!!!!!!!!******oooooeeeeee&&&&&&############%%%%%%%%%%%%%%%
&&eeeooo******!!!!!!!!!!********ooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%%
#&&eeeooooo******************oooooooeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%%
#&&&eeeeoooooooo******oooooooooooeeeeeee&&&&&&&&#############%%%%%%%%%%%%%%%%%%
##&&&&eeeeeooooooooooooooooooeeeeeeee&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%
##&&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&################%%%%%%%%%%%%%%%%%%%
####&&&&&&eeeeeeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%%
#####&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%%
%#######&&&&&&&&&&&&&&&&&&&&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%
%###########&&&&&&&&&&&&&#######################%%%%%%%%%%%%%%%%%%%%%%%%%
%############################################%%%%%%%%%%%%%%%%%%%%%%%%%%
%%#######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%#################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%#########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%#############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%

::...:::!!!*o
..............::!!*oo
..................::!!**ooe
.....................::!!**ooee
.......................::!!**ooee
........................::!!**oooee
.........................::!!**oooeee
:........................::!!!**oooeeee
........................::!!!**ooooeeee
:......................::!!!***oooeeeee
:....................:::!!!***oooeeeeee
!:.................:::!!!****oooeeeeeee
*!:::...........::::!!!!***ooooeeeeeeee
*!!!:::::::::::!!!!!****oooooeeeeeeee
o**!!!!!!!!!!!!!*****oooooeeeeeeeee
oo**************ooooooeeeeeeeeeee
eoooooooooooooooooeeeeeeeeeeeee
eeeooooooooeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeee

## V (Vlang)

Graphical

import gg
import gx

const (
win_width  = 600
win_height = 600
)

struct App {
mut:
gg    &gg.Context = unsafe {nil}
}

fn main() {
mut app := &App{
gg: 0
}
app.gg = gg.new_context(
bg_color: gx.white
width: win_width
height: win_height
create_window: true
window_title: 'Circle'
frame_fn: frame
user_data: app
)
app.gg.run()
}

fn frame(app &App) {
app.gg.begin()
app.draw()
app.gg.end()
}

fn (app &App) draw() {
app.gg.draw_circle_filled(300, 300, 150, gx.red)
}


## Wren

Translation of: C
var shades = ".:!*oe&#\%@"
var light = [30, 30, -50]

var normalize = Fn.new { |v|
var len = (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]).sqrt
for (i in 0..2) v[i] =  v[i] / len
}

var dot = Fn.new { |x, y|
var d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2]
return (d < 0) ? -d : 0
}

var drawSphere = Fn.new { |r, k, ambient|
var vec = [0] * 3
for (i in (-r).floor..r.ceil) {
var x = i + 0.5
for (j in (-2*r).floor..(2*r).ceil) {
var y = j/2 + 0.5
if (x*x + y*y <= r*r) {
var vec = [x, y, (r*r - x*x - y*y).sqrt]
normalize.call(vec)
var b = dot.call(light, vec).pow(k) + ambient
var intensity = ((1 - b) * (shades.count - 1)).truncate
if (intensity < 0) intensity = 0
} else {
System.write(" ")
}
}
System.print()
}
}

normalize.call(light)
drawSphere.call(20, 4, 0.1)
drawSphere.call(10, 2, 0.4)

Output:
                               &&&&&&&&&&#######
&eeeeeeeeeeeeeeee&&&&&&#######%
&eoooo*******oooooooeeeee&&&&&########%
eoo****!!!!!!!!******oooooeeee&&&&&########%%
eoo**!!!!::::::::!!!!!*****ooooeeee&&&&&########%%%
eo**!!::::::...:::::::!!!!!***ooooeeee&&&&&########%%%%
eo*!!:::.............:::::!!!!***ooooeeee&&&&&########%%%%%
eo*!!:::.................::::!!!!***ooooeeee&&&&#########%%%%%%
eo*!!::....................::::!!!****oooeeee&&&&&#########%%%%%%
&o**!::......................::::!!!****oooeeee&&&&&##########%%%%%%%
&o**!::.......................::::!!!****oooeeee&&&&&##########%%%%%%%%
&oo*!!::.......................:::!!!!***ooooeeee&&&&&##########%%%%%%%%%
&eo*!!::.......................::::!!!****ooooeeee&&&&&##########%%%%%%%%%%
eo**!!::......................::::!!!!***ooooeeeee&&&&&##########%%%%%%%%%%
&eo**!!:::...................:::::!!!!****ooooeeee&&&&&###########%%%%%%%%%%%
eeo**!!::::................:::::!!!!!****ooooeeee&&&&&&###########%%%%%%%%%%%
&eeo***!!:::::...........::::::!!!!!****oooooeeee&&&&&&###########%%%%%%%%%%%%%
&eeoo**!!!!::::::::::::::::::!!!!!*****ooooeeeee&&&&&&############%%%%%%%%%%%%%
&eeooo***!!!!::::::::::::!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%%
&&eeooo***!!!!!!!!!!!!!!!!!!!******oooooeeeeee&&&&&&############%%%%%%%%%%%%%%%
&&eeeooo******!!!!!!!!!!********ooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%%
#&&eeeooooo******************oooooooeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%%
#&&&eeeeoooooooo******oooooooooooeeeeeee&&&&&&&&#############%%%%%%%%%%%%%%%%%%
##&&&&eeeeeooooooooooooooooooeeeeeeee&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%
##&&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&################%%%%%%%%%%%%%%%%%%%
####&&&&&&eeeeeeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%%
#####&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%%
%#######&&&&&&&&&&&&&&&&&&&&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%
%###########&&&&&&&&&&&&&#######################%%%%%%%%%%%%%%%%%%%%%%%%%
%############################################%%%%%%%%%%%%%%%%%%%%%%%%%%
%%#######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%#################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%#########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%#############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%

::...:::!!!*o
..............::!!*oo
..................::!!**ooe
.....................::!!**ooee
.......................::!!**ooee
........................::!!**oooee
.........................::!!**oooeee
:........................::!!!**oooeeee
........................::!!!**ooooeeee
:......................::!!!***oooeeeee
:....................:::!!!***oooeeeeee
!:.................:::!!!****oooeeeeeee
*!:::...........::::!!!!***ooooeeeeeeee
*!!!:::::::::::!!!!!****oooooeeeeeeee
o**!!!!!!!!!!!!!*****oooooeeeeeeeee
oo**************ooooooeeeeeeeeeee
eoooooooooooooooooeeeeeeeeeeeee
eeeooooooooeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeee


## XPL0

include c:\cxpl\codes;          \intrinsic 'code' declarations
def     X0=640/2, Y0=480/2;     \coordinates of center of screen
int     X, Y, Z, C, D2;         \coords, color, distance from center squared
[SetVid($112); \set 640x480x24 graphics mode for Y:= -R to +R do \for all the coordinates near the circle for X:= -R to +R do \ which is under the sphere [D2:= X*X + Y*Y; C:= 0; \default color is black if D2 <= R2 then \coordinate is inside circle under sphere [Z:= sqrt(R2-D2); \height of point on surface of sphere above X,Y C:= Z-(X+Y)/2+130; \color is proportional; offset X and Y, and ]; \ shift color to upper limit of its range Point(X+X0, Y+Y0, C<<8+C); \green + blue = cyan ]; repeat until KeyHit; \wait for keystroke SetVid($03);                    \restore normal text mode
]

## Yabasic

ancho = 640 : alto = 480
open window 640,480
backcolor 16,16,16
clear window
sphera()

sub sphera()
local n

for n = 1 to 100
color 2*n, 2*n, 2*n
fill circle ancho/2-2*n/3, alto/2-n/2, 150-n
next n
end sub

## Zig

Translation of: Factor
Library: raylib
const std = @import("std");
const c = @cImport({
@cInclude("raylib.h");
});

pub fn main() !void {
c.SetConfigFlags(c.FLAG_WINDOW_RESIZABLE | c.FLAG_VSYNC_HINT);
c.InitWindow(600, 480, "Draw a Sphere");
defer c.CloseWindow();

const camera = c.Camera3D{
.position = .{ .x = 4.5, .y = 4.5, .z = 4.5 },
.target = .{ .x = 0, .y = 0, .z = 0 },
.up = .{ .x = 0, .y = 1, .z = 0 },
.fovy = 45.0,
.projection = c.CAMERA_PERSPECTIVE,
};

c.SetTargetFPS(60);

while (!c.WindowShouldClose()) {
c.BeginDrawing();
defer c.EndDrawing();

c.ClearBackground(c.BLACK);

{
c.BeginMode3D(camera);
defer c.EndMode3D();

c.DrawSphereWires(.{ .x = 0, .y = 0, .z = 0 }, 2, 20, 20, c.LIME);
}
}
}


## zkl

Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

Translation of: XPL0
img:=PPM(640,480);
X0:=640/2; Y0:=480/2;      //coordinates of center of screen
foreach Y in ([-R..R]){    //for all the coordinates near the circle
foreach X in ([-R..R]){ // which is under the sphere
D2:=X*X + Y*Y;
C:=0;                //default color is black
if(D2<=R2){          //coordinate is inside circle under sphere
Z:=(R2-D2).toFloat().sqrt();//height of point on surface of sphere above X,Y
C=0x82+Z-(X+Y)/2; //color is proportional; offset X and Y, and
}                    // shift color to upper limit of its range
img[X+X0,Y+Y0]=C.shiftLeft(8)+C; //green + blue = cyan
}
}
img.write(File("foo.ppm","wb"));

The radius of 100 is the max before the color calculation overflows 24 bits so for a radius (R) of, say 200, use

img[X+X0,Y+Y0]=C*140+C;

Perhaps a more useful solution is to use GnuPlot (I grabbed the code from http://ayapin-film.sakura.ne.jp/Gnuplot/):

#<<<
cmd:=0'|
set term wxt
set parametric
set urange [0:pi]
set vrange [0:2*pi]
set xyplane 0
set view equal xyz
set pm3d hidden3d 100 depthorder
set style line 100 lt 7 lw 0.1
set palette defined (0 "dark-blue", 1 "light-blue")
unset key
set samples 24
set isosamples 36
set title 'sphere (pm3d)' font "Times,20"
R = 3
splot R*sin(u)*cos(v), R*sin(u)*sin(v), R*cos(u) w pm3d
|;
#<<<

gnuplot:=System.popen("gnuplot","w");
gnuplot.write(cmd); gnuplot.flush();
ask("Hit return to finish"); gnuplot.close();

Where "term wxt" is X11 on my Linux box. A window pops up and stays until the pipe is closed.

## ZX Spectrum Basic

1 REM fast
50 REM spheer with hidden lines and rotation
100 CLS
110 PRINT "sphere with lenght&wide-circles"
120 PRINT "_______________________________"''
200 INPUT "rotate x-as:";a
210 INPUT "rotate y-as:";b
220 INPUT "rotate z-as:";c
225 INPUT "distance lines(10-45):";d
230 LET u=128: LET v=87: LET r=87: LET bm=PI/180: LET h=.5
240 LET s1=SIN (a*bm): LET s2=SIN (b*bm): LET s3=SIN (c*bm)
250 LET c1=COS (a*bm): LET c2=COS (b*bm): LET c3=COS (c*bm)
260 REM calc rotate matrix
270 LET ax=c2*c3: LET ay=-c2*s3: LET az=s2
280 LET bx=c1*s3+s1*s2*c3
290 LET by=c1*c3-s1*s2*s3: LET bz=-s1*c2
300 LET cx=s1*s3-c1*s2*c3
310 LET cy=s1*c3+c1*s2*s3: LET cz=c1*c2
400 REM draw outer
410 CLS : CIRCLE u,v,r
500 REM draw lenght-circle
510 FOR l=0 TO 180-d STEP d
515 LET f1=0
520 FOR p=0 TO 360 STEP 5
530 GO SUB 1000: REM xx,yy,zz calc
540 IF yy>0 THEN LET f2=0: LET f1=0: GO TO 580
550 LET xb=INT (u+xx+h): LET yb=INT (v+zz+h): LET f2=1
560 IF f1=0 THEN LET x1=xb: LET y1=yb: LET f1=1: GO TO 580
570 PLOT x1,y1: DRAW xb-x1,yb-y1: LET x1=xb: LET y1=yb: LET f1=f2
580 NEXT p
590 NEXT l
600 REM draw wide-circle
610 FOR p=-90+d TO 90-d STEP d
615 LET f1=0
620 FOR l=0 TO 360 STEP 5
630 GO SUB 1000: REM xx,yy,zz
640 IF yy>0 THEN LET f2=0: LET f1=0: GO TO 680
650 LET xb=INT (u+xx+h): LET yb=INT (v+zz+h): LET f2=1
660 IF f1=0 THEN LET x1=xb: LET y1=yb: LET f1=1: GO TO 680
670 PLOT x1,y1: DRAW xb-x1,yb-y1: LET x1=xb: LET y1=yb: LET f1=f2
680 NEXT l
690 NEXT p
700 PRINT #0;"...press any key...": PAUSE 0: RUN
999 REM sfere-coordinates>>>Cartesis Coordinate
1000 LET x=r*COS (p*bm)*COS (l*bm)
1010 LET y=r*COS (p*bm)*SIN (l*bm)
1020 LET z=r*SIN (p*bm)
1030 REM p(x,y,z) rotate to p(xx,yy,zz)
1040 LET xx=ax*x+ay*y+az*z
1050 LET yy=bx*x+by*y+bz*z
1060 LET zz=cx*x+cy*y+cz*z
1070 RETURN`