Skip to content

Commit b0480f9

Browse files
committed
Init
1 parent d1023b2 commit b0480f9

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
build*/
2+
13
# Prerequisites
24
*.d
35

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
cmake_minimum_required(VERSION 3.14...3.22)
2+
3+
project(DonutFortran LANGUAGES Fortran)
4+
5+
enable_testing()
6+
7+
add_executable(donut donut.f90)

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
11
# fortran-donut
2+
23
Fortran terminal spinning 3D-like donut
4+
5+
The earliest implementation I found in C was at this [2011 Gist](https://gist.github.com/gcr/1075131).
6+
I fixed some bugs in this (array bounds).
7+
I also sped it up dramatically by writing line-by-line instead of character-by-character--this also reduces screen printing artifacts.
8+
9+
Works in Linux/macOS and Windows Terminal, using escape codes to position cursor and clear screen.
10+
11+
## options
12+
13+
`-frames 1000`: 1000 frames before exit
14+
`-dump file.txt`: dump each frame to a file
15+
16+
## Notes
17+
18+
other [Fortran donut](https://github.com/ShrirajHegde/ASCII-Donut-FORTRAN)

donut.f90

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
program donut
2+
3+
use, intrinsic :: iso_fortran_env, only : wp=>real64, stdout => output_unit
4+
5+
implicit none (type, external)
6+
7+
character, parameter :: ESC = achar(27)
8+
character, parameter :: TAB(0:11) = [".", ",", "-", "~", ":", ";", "=", "!", "*", "#", "$", "@"]
9+
real(wp), parameter :: PI = 4*atan(1.)
10+
11+
integer :: cols, rows, L, k
12+
13+
real(wp) :: a=0, b=0, i, j
14+
15+
real(wp), allocatable :: z(:)
16+
character, allocatable :: screen(:)
17+
18+
real(wp) :: sini,cosj,sinA,sinj,cosA,cosj2, mess, cosi,cosB,t,sinB
19+
integer :: x,y,o,N,ii, u, Nloop
20+
character(5) :: buf
21+
character(:), allocatable :: dumpfn
22+
23+
Nloop = 100
24+
do ii = 1, command_argument_count()
25+
call get_command_argument(ii, buf)
26+
27+
select case (buf)
28+
case ("-dump")
29+
call get_command_argument(ii+1, buf, status=k)
30+
if (k==0) dumpfn = trim(buf)
31+
case ("-frames")
32+
call get_command_argument(ii+1, buf, status=k)
33+
if (k==0) read(buf, '(I5)') Nloop
34+
end select
35+
enddo
36+
37+
38+
cols = 80
39+
rows = 22
40+
L = rows*cols
41+
42+
allocate(z(0:L-1), screen(0:L-1))
43+
44+
if(allocated(dumpfn)) open(newunit=u, file=dumpfn, status='replace', action='write')
45+
46+
write(stdout,"(a)", advance="no") ESC // "[2J" !< move cursor to top left
47+
48+
do ii = 1,Nloop
49+
z=0
50+
screen=""
51+
j=0
52+
do while(2*pi > j)
53+
i=0
54+
do while(2*pi > i)
55+
sini = sin(i)
56+
cosj = cos(j)
57+
sinA = sin(a)
58+
sinj = sin(j)
59+
cosA = cos(a)
60+
cosj2 = cosj+2
61+
mess = 1 / (sini*cosj2*sinA+sinj*cosA+5)
62+
cosi=cos(i)
63+
cosB=cos(b)
64+
sinB=sin(b)
65+
t = sini*cosj2*cosA - sinj*sinA
66+
x = 40 + 30*mess*(cosi*cosj2*cosB - t*sinB)
67+
y = 12 + 15*mess*(cosi*cosj2*sinB + t*cosB)
68+
o = min(L, x+cols*y) !< C program goes out of bounds
69+
N = int(8*((sinj*sinA - sini*cosj*cosA)*cosB - sini*cosj*sinA - sinj*cosA - cosi * cosj*sinB))
70+
if(rows>y .and. y>0 .and. x>0 .and. cols>x .and. mess>z(o)) then
71+
z(o)=mess
72+
screen(o) = TAB(max(N,0))
73+
endif
74+
i = i + 0.02
75+
enddo
76+
j = j + 0.07
77+
enddo
78+
79+
write(stdout, "(a)", advance="no") ESC // "[d" !< line feed
80+
81+
do k=0, rows-2
82+
print *, screen(k*cols:k*cols+cols)
83+
if(allocated(dumpfn)) write(u, "(80a)") screen(k*cols:k*cols+cols)
84+
enddo
85+
86+
! print *, size(screen), k*cols,k*cols+cols
87+
88+
a = a + 0.04
89+
b = b + 0.02
90+
enddo
91+
92+
if(allocated(dumpfn)) close(u)
93+
94+
end program

0 commit comments

Comments
 (0)