Archimedean spiral: Difference between revisions
(Ada version) |
(Added Algol 68; Reduced font size for the ASCII art output) |
||
(104 intermediate revisions by 39 users not shown) | |||
Line 1: | Line 1: | ||
{{task}} |
{{task}} |
||
[[File:Archimedian spiral j.png|300px|right]] |
|||
The [[wp:Archimedean_spiral|Archimedean spiral]] is a spiral named after the Greek mathematician Archimedes. |
The [[wp:Archimedean_spiral|Archimedean spiral]] is a spiral named after the Greek mathematician Archimedes. |
||
Line 13: | Line 14: | ||
;Task |
;Task |
||
Draw an Archimedean spiral. |
Draw an Archimedean spiral. |
||
<br |
<br><br> |
||
=={{header|Action!}}== |
|||
Action! does not provide trigonometric functions. Therefore a simple implementation for Sin and Cos function has been provided. |
|||
<syntaxhighlight lang="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 DrawSpiral(INT x0,y0) |
|||
INT angle,radius,x,y |
|||
Plot(x0,y0) |
|||
FOR angle=0 TO 1800 STEP 5 |
|||
DO |
|||
radius=angle/20 |
|||
x=radius*Cos(angle)/256+x0 |
|||
y=radius*Sin(angle)/256+y0 |
|||
DrawTo(x,y) |
|||
OD |
|||
RETURN |
|||
PROC Main() |
|||
BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6 |
|||
Graphics(8+16) |
|||
Color=1 |
|||
COLOR1=$0C |
|||
COLOR2=$02 |
|||
DrawSpiral(160,96) |
|||
DO UNTIL CH#$FF OD |
|||
CH=$FF |
|||
RETURN</syntaxhighlight> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Archimedean_spiral.png Screenshot from Atari 8-bit computer] |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
{{libheader|SDLAda}} |
{{libheader|SDLAda}} |
||
< |
<syntaxhighlight lang="ada">with Ada.Numerics.Elementary_Functions; |
||
with SDL.Video.Windows.Makers; |
with SDL.Video.Windows.Makers; |
||
with SDL.Video. |
with SDL.Video.Renderers.Makers; |
||
with SDL.Video.Rectangles; |
|||
with SDL.Video.Pixel_Formats; |
|||
with SDL.Events.Events; |
with SDL.Events.Events; |
||
Line 35: | Line 89: | ||
T_Last : constant := 100.0; |
T_Last : constant := 100.0; |
||
Window : SDL.Video.Windows.Window; |
|||
Renderer : SDL.Video.Renderers.Renderer; |
|||
Event : SDL.Events.Events.Events; |
Event : SDL.Events.Events.Events; |
||
procedure Plot (X, Y : Float) is |
|||
use SDL.C; |
|||
Point : constant SDL.Video.Rectangles.Rectangle |
|||
:= (X => Width / 2 + SDL.C.int (X), |
|||
Y => Height / 2 + SDL.C.int (Y), |
|||
Width => 2, Height => 2); |
|||
begin |
|||
Surface.Fill (Point, SDL.Video.Pixel_Formats.To_Pixel |
|||
(Format => Surface.Pixel_Format, |
|||
Red => 0, Green => 250, Blue => 0)); |
|||
end Plot; |
|||
procedure Draw_Archimedean_Spiral is |
procedure Draw_Archimedean_Spiral is |
||
use type SDL.C.int; |
|||
use Ada.Numerics.Elementary_Functions; |
use Ada.Numerics.Elementary_Functions; |
||
Pi : constant := Ada.Numerics.Pi; |
Pi : constant := Ada.Numerics.Pi; |
||
Step : constant := 0. |
Step : constant := 0.002; |
||
T : Float; |
T : Float; |
||
R : Float; |
R : Float; |
||
Line 61: | Line 104: | ||
loop |
loop |
||
R := A + B * T; |
R := A + B * T; |
||
Renderer.Draw |
|||
Plot (X => R * Cos (T, Cycle => 2.0 * Pi), |
|||
(Point => (X => Width / 2 + SDL.C.int (R * Cos (T, 2.0 * Pi)), |
|||
Y => Height / 2 - SDL.C.int (R * Sin (T, 2.0 * Pi)))); |
|||
exit when T >= T_Last; |
exit when T >= T_Last; |
||
T := T + Step; |
T := T + Step; |
||
Line 85: | Line 129: | ||
end if; |
end if; |
||
SDL.Video.Windows.Makers.Create (Win => |
SDL.Video.Windows.Makers.Create (Win => Window, |
||
Title => "Archimedean spiral", |
Title => "Archimedean spiral", |
||
Position => SDL.Natural_Coordinates'(X => 10, Y => 10), |
Position => SDL.Natural_Coordinates'(X => 10, Y => 10), |
||
Size => SDL.Positive_Sizes'(Width, Height), |
Size => SDL.Positive_Sizes'(Width, Height), |
||
Flags => 0); |
Flags => 0); |
||
SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface); |
|||
Renderer.Set_Draw_Colour ((0, 0, 0, 255)); |
|||
Renderer.Fill (Rectangle => (0, 0, Width, Height)); |
|||
Renderer.Set_Draw_Colour ((0, 220, 0, 255)); |
|||
SDL.Video.Pixel_Formats.To_Pixel |
|||
(Format => Surface.Pixel_Format, |
|||
Red => 0, Green => 0, Blue => 0)); |
|||
Draw_Archimedean_Spiral; |
Draw_Archimedean_Spiral; |
||
Window.Update_Surface; |
|||
Wait; |
Wait; |
||
Window.Finalize; |
|||
SDL.Finalise; |
SDL.Finalise; |
||
end Archimedean_Spiral;</ |
end Archimedean_Spiral;</syntaxhighlight> |
||
=={{header|ALGOL 68}}== |
|||
ASCII art. |
|||
{{Trans|ALGOL W}} |
|||
<syntaxhighlight lang="algol68"> |
|||
BEGIN # draw an Archimedian spiral using ASCII art # |
|||
# Translation of Applesoft Basic via AWK and Algol W # |
|||
PROC max = ( INT x, y )INT: IF x > y THEN x ELSE y FI; |
|||
PROC min = ( INT x, y )INT: IF x < y THEN x ELSE y FI; |
|||
[ 1 : 255, 1 : 255 ]CHAR arr; |
|||
FOR i FROM 1 LWB arr TO 1 UPB arr DO |
|||
FOR j FROM 2 LWB arr TO 2 UPB arr DO arr[ i, j ] := " " OD |
|||
OD; |
|||
INT x min := 1 UPB arr + 1, y min := 2 UPB arr + 1; |
|||
INT x max := 1 LWB arr - 1, y max := 2 LWB arr - 1; |
|||
REAL m = 6 * pi, h = 96, s = 0.02; |
|||
REAL w = 1.5 * h; |
|||
REAL t := s; |
|||
WHILE t <= m DO # build spiral # |
|||
REAL r = t + 1; |
|||
INT x = ROUND ( r * cos( t ) + w ); |
|||
INT y = ROUND ( r * sin( t ) + h ); |
|||
IF x >= 1 LWB arr AND y >= 2 LWB arr |
|||
AND x <= 1 UPB arr AND y <= 2 UPB arr |
|||
THEN |
|||
arr[ x, y ] := "*"; |
|||
x min := min( x min, x ); |
|||
x max := max( x max, x ); |
|||
y min := min( y min, y ); |
|||
y max := max( y max, y ); |
|||
FI; |
|||
t +:= s |
|||
OD; |
|||
FOR i FROM x min TO x max DO # print spiral # |
|||
FOR j FROM y min TO y max DO |
|||
CHAR c = arr[ i, j ]; |
|||
print( ( c, c ) ) |
|||
OD; |
|||
print( ( newline ) ) |
|||
OD |
|||
END |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="font-size: 50%;"> |
|||
************** |
|||
******** ******** |
|||
****** **** |
|||
**** ****** |
|||
**** **** |
|||
**** **** |
|||
**** **** |
|||
**** ****************** ** |
|||
**** **** ****** ** |
|||
** **** **** **** |
|||
**** ** **** ** |
|||
** **** **** ** |
|||
** **** ** ** |
|||
** ** ********** **** ** |
|||
** **** **** **** ** ** |
|||
** ** ** **** ** ** |
|||
** ** **** ** ** ** |
|||
** ** ** **** ** ** |
|||
** ** ** ****** ** ** |
|||
** ** ** **** ** |
|||
** ** **** ** ** |
|||
** ** ** **** ** |
|||
** ** **** **** ** |
|||
** ** ****** **** **** |
|||
** **** ************** ** |
|||
** ** ** |
|||
**** ** **** |
|||
** **** **** |
|||
**** **** ****** |
|||
** ****** ****** |
|||
** ******** ******** |
|||
** ********** |
|||
** |
|||
**** |
|||
****** |
|||
****** |
|||
******** |
|||
******** |
|||
</pre> |
|||
=={{header|ALGOL W}}== |
|||
{{Trans|AWK}} |
|||
This version doubles the characters horiontally to give a slightly more rounded shape. |
|||
<syntaxhighlight lang="algolw">begin % draw an Archimedian spiral % |
|||
% Translation of AWK which was a trnslation of Applesoft Basic program % |
|||
integer procedure max ( integer x, y ) ; begin if x > y then x else y end; |
|||
integer procedure min ( integer x, y ) ; begin if x < y then x else y end; |
|||
integer x_min, y_min, x_max, y_max, x, y; |
|||
string(255) array arr ( 1 :: 255 ); |
|||
real h, w, m, s, t; |
|||
for i := 1 until 255 do arr( i ) := " "; |
|||
x_min := y_min := 9999; |
|||
x_max := y_max := 0; |
|||
h := 96; |
|||
w := h + h / 2; |
|||
m := 6 * PI; |
|||
s := 0.02; |
|||
t := s; |
|||
while t <= m do begin % build spiral % |
|||
real r; |
|||
r := t + 1; |
|||
x := round(r * cos(t) + w); |
|||
y := round(r * sin(t) + h); |
|||
if x > 0 and y > 0 and x < 256 and y < 256 then begin |
|||
arr( x )( y // 1 ) := "*"; |
|||
x_min := min(x_min,x); |
|||
x_max := max(x_max,x); |
|||
y_min := min(y_min,y); |
|||
y_max := max(y_max,y) |
|||
end if_x_and_y_in_range ; |
|||
t := t + s |
|||
end while__t_le_m ; |
|||
for i := x_min until x_max do begin % print spiral % |
|||
for j := y_min until y_max do begin |
|||
string(1) c; |
|||
c := arr( i )( j // 1 ); |
|||
writeon( c, c ) |
|||
end for_j ; |
|||
write() |
|||
end for_i |
|||
end. |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="font-size: 50%;"> |
|||
************** |
|||
******** ******** |
|||
****** **** |
|||
**** ****** |
|||
**** **** |
|||
**** **** |
|||
**** **** |
|||
**** ****************** ** |
|||
**** **** ****** ** |
|||
** **** **** **** |
|||
**** ** **** ** |
|||
** **** **** ** |
|||
** **** ** ** |
|||
** ** ********** **** ** |
|||
** **** **** **** ** ** |
|||
** ** ** **** ** ** |
|||
** ** **** ** ** ** |
|||
** ** ** **** ** ** |
|||
** ** ** ****** ** ** |
|||
** ** ** **** ** |
|||
** ** **** ** ** |
|||
** ** ** **** ** |
|||
** ** **** **** ** |
|||
** ** ****** **** **** |
|||
** **** ************** ** |
|||
** ** ** |
|||
**** ** **** |
|||
** **** **** |
|||
**** **** ****** |
|||
** ****** ****** |
|||
** ******** ******** |
|||
** ********** |
|||
** |
|||
**** |
|||
****** |
|||
****** |
|||
******** |
|||
******** |
|||
</pre> |
|||
=={{header|Amazing Hopper}}== |
|||
{{Trans|AmigaBASIC}} |
|||
[[File:Captura_de_pantalla_de_2022-10-07_22-57-32.png|200px|thumb|right]] |
|||
<syntaxhighlight lang="c"> |
|||
#include <jambo.h> |
|||
Main |
|||
Set break |
|||
a=1.5, b=1.5, r=0, origen x=200, origen y=105 |
|||
total = 0, Let ( total := Mul(20, M_PI) ) |
|||
Cls |
|||
Loop for ( t=0, var 't' Is less equal to 'total', Let (t := Add (t, 0.005)) ) |
|||
#( r = a + b * t ) |
|||
Set 'origen x, origen y', # ( 200 + (2*r*sin(t)) ) » 'origen x', #( 105 + (r*cos(t)) ) » 'origen y', |
|||
Gosub 'Dibuja un segmento' |
|||
Next |
|||
Pause |
|||
End |
|||
Subrutines |
|||
Define (Dibuja un segmento, x1, y1, x2, y2) |
|||
dx=0, dy=0, paso=0, i=0, DX=0, DY=0 |
|||
Sub(x2, x1), Sub (y2, y1), Move to ' dx, dy ' |
|||
Let( paso := Get if( Greater equal ( Abs(dx) » (DX), Abs(dy)»(DY) ), DX, DY ) ) |
|||
// incremento: |
|||
Div(dx, paso), Div(dy, paso), Move to ( dx, dy ) |
|||
Color back (13) |
|||
// dibuja línea: |
|||
i = 0 |
|||
Loop if ( Less equal (i, paso) ) |
|||
Locate( y1, x1 ), Printnl( " " ) |
|||
Add ( x1, dx), Add( y1, dy ), Move to ( x1, y1 ) |
|||
++i |
|||
Back |
|||
Printnl("\OFF") |
|||
Return |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Invocar como: |
|||
rxvt -g 500x250 -fn "xft:FantasqueSansMono-Regular:pixelsize=1" -e hopper jm/archi.jambo |
|||
</pre> |
|||
=={{header|APL}}== |
|||
'''Works in: [[Dyalog APL]]''' |
|||
Uses Dyalog's [https://sharpplot.com/ SharpPlot] integration, which works on all supported platforms. |
|||
<syntaxhighlight lang="apl"> 'InitCauseway' 'View' ⎕CY 'sharpplot' |
|||
InitCauseway ⍬ ⍝ initialise current namespace |
|||
sp←⎕NEW Causeway.SharpPlot |
|||
sp.DrawPolarChart {⍵(360|⍵)}⌽⍳720 |
|||
View sp</syntaxhighlight> |
|||
[https://i.imgur.com/hZDqjjM.png See the plot on imgur.] |
|||
=={{header|AutoHotkey}}== |
|||
Requires [https://github.com/tariqporter/Gdip GDIP] |
|||
<syntaxhighlight lang="autohotkey">if !pToken := Gdip_Startup() |
|||
{ |
|||
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system |
|||
ExitApp |
|||
} |
|||
OnExit, Exit |
|||
SysGet, MonitorPrimary, MonitorPrimary |
|||
SysGet, WA, MonitorWorkArea, %MonitorPrimary% |
|||
WAWidth := WARight-WALeft |
|||
WAHeight := WABottom-WATop |
|||
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs |
|||
Gui, 1: Show, NA |
|||
hwnd1 := WinExist() |
|||
hbm := CreateDIBSection(WAWidth, WAHeight) |
|||
hdc := CreateCompatibleDC() |
|||
obm := SelectObject(hdc, hbm) |
|||
G := Gdip_GraphicsFromHDC(hdc) |
|||
Gdip_SetSmoothingMode(G, 4) |
|||
pPen := Gdip_CreatePen(0xffff0000, 3) |
|||
;-------------------------------- |
|||
a := 1, b := 4, th := 0.1, step := 0.1 |
|||
loop, 720 |
|||
{ |
|||
th += step |
|||
r := a + b * th |
|||
x1 := r * Cos(th) |
|||
y1 := r * Sin(th) |
|||
x1 += A_ScreenWidth/2 |
|||
y1 += A_ScreenHeight/2 |
|||
if (x2 && y2) |
|||
Gdip_DrawLine(G, pPen, x1, y1, x2, y2) |
|||
x2 := x1, y2 := y1 |
|||
if GetKeyState("Esc", "P") |
|||
break |
|||
; next two lines are optional to watch it draw |
|||
; Sleep 10 |
|||
; UpdateLayeredWindow(hwnd1, hdc, WALeft, WATop, WAWidth, WAHeight) |
|||
} |
|||
UpdateLayeredWindow(hwnd1, hdc, WALeft, WATop, WAWidth, WAHeight) |
|||
;-------------------------------- |
|||
return |
|||
Exit: |
|||
Gdip_DeletePen(pPen) |
|||
SelectObject(hdc, obm) |
|||
DeleteObject(hbm) |
|||
DeleteDC(hdc) |
|||
Gdip_DeleteGraphics(G) |
|||
Gdip_Shutdown(pToken) |
|||
ExitApp |
|||
Return</syntaxhighlight> |
|||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
<syntaxhighlight lang="awk"> |
|||
<lang AWK> |
|||
# syntax: GAWK -f ARCHIMEDEAN_SPIRAL.AWK |
# syntax: GAWK -f ARCHIMEDEAN_SPIRAL.AWK |
||
# converted from Applesoft BASIC |
# converted from Applesoft BASIC |
||
Line 142: | Line 469: | ||
function max(x,y) { return((x > y) ? x : y) } |
function max(x,y) { return((x > y) ? x : y) } |
||
function min(x,y) { return((x < y) ? x : y) } |
function min(x,y) { return((x < y) ? x : y) } |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 183: | Line 510: | ||
***** |
***** |
||
</pre> |
</pre> |
||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
==={{header|AmigaBASIC}}=== |
|||
{{trans|Locomotive Basic}} |
|||
[[File:Amigabasic spiral.png|thumb|Output]] |
|||
<syntaxhighlight lang="qbasic">a=1.5 |
|||
b=1.5 |
|||
pi=3.141592 |
|||
PSET (320,100) |
|||
FOR t=0 TO 40*pi STEP .1 |
|||
r=a+b*t |
|||
LINE -(320+2*r*SIN(t),100+r*COS(t)) |
|||
NEXT</syntaxhighlight> |
|||
==={{header|Applesoft BASIC}}=== |
==={{header|Applesoft BASIC}}=== |
||
< |
<syntaxhighlight lang="applesoftbasic">110 LET H = 96 |
||
120 LET W = H + H / 2 |
120 LET W = H + H / 2 |
||
130 HGR2 |
130 HGR2 |
||
Line 205: | Line 545: | ||
280 HPLOT X,Y |
280 HPLOT X,Y |
||
290 NEXT |
290 NEXT |
||
</syntaxhighlight> |
|||
</lang> |
|||
==={{header|BASIC256}}=== |
==={{header|BASIC256}}=== |
||
<syntaxhighlight lang="basic256"> |
|||
<lang BASIC256> |
|||
# Basic-256 ver 1.1.4 |
# Basic-256 ver 1.1.4 |
||
# Archimedean Spiral |
# Archimedean Spiral |
||
Line 221: | Line 561: | ||
i = 1 : t = 0 : xn = 0 : yn = 0 # Initial values |
i = 1 : t = 0 : xn = 0 : yn = 0 # Initial values |
||
iter = 150 : q = 30 |
iter = 150 : q = 30 |
||
line x,0,x,height |
line x,0,x,height |
||
Line 237: | Line 576: | ||
print i + chr(9) + int(x) + chr(9) + int(y) + chr(9) + int(t) # chr(9) = TAB |
print i + chr(9) + int(x) + chr(9) + int(y) + chr(9) + int(t) # chr(9) = TAB |
||
i += 1 |
i += 1 |
||
end while |
end while |
||
imgsave "spiral-Basic-256.png", "PNG" |
imgsave "spiral-Basic-256.png", "PNG" |
||
</syntaxhighlight> |
|||
</lang> |
|||
==={{header|BBC BASIC}}=== |
|||
{{works with|BBC BASIC for Windows}} |
|||
[[File:Archimedean_spiral_bbc_basic.jpeg|300px|right]] |
|||
<syntaxhighlight lang="bbcbasic"> A=320 |
|||
VDU 23, 22, A+10; A+10; 8, 16, 16, 128 |
|||
ORIGIN @size.x%, @size.y% |
|||
GCOL 7 |
|||
FOR I=-(A - A MOD 100) TO A - A MOD 100 STEP 100 |
|||
LINE I, -A, I, A : LINE -A, I, A, I |
|||
NEXT |
|||
MOVE 0, 0 |
|||
GCOL 1 |
|||
VDU 23, 23, 3| |
|||
FOR I=0 TO 5 * PI STEP .05 |
|||
R=A / 16 * I |
|||
DRAW R * COS(I), R * SIN(I) |
|||
NEXT |
|||
</syntaxhighlight> |
|||
==={{header|Chipmunk Basic}}=== |
|||
{{works with|Chipmunk Basic|3.6.4}} |
|||
<syntaxhighlight lang="basic"> |
|||
10 rem Archimedean spiral |
|||
20 graphics 0 |
|||
30 graphics cls |
|||
40 a = 3 : b = 1.4 |
|||
50 x0 = 320 : y0 = 200 |
|||
60 graphics moveto x0,y0 |
|||
70 for t = 0 to 40*pi step 0.2 |
|||
80 r = a+b*t |
|||
90 x = r*cos(t)+320 : y = r*sin(t)+200 |
|||
100 graphics lineto x,y |
|||
110 next t |
|||
120 end |
|||
</syntaxhighlight> |
|||
==={{header|Commodore BASIC}}=== |
==={{header|Commodore BASIC}}=== |
||
Commodore BASIC 2.0 lacks in-built graphics capability. This implementation is written for Commodore BASIC 7.0 that was built into the Commodore 128 computer. Should also work for Commodore BASIC 3.5. |
Commodore BASIC 2.0 lacks in-built graphics capability. This implementation is written for Commodore BASIC 7.0 that was built into the Commodore 128 computer. Should also work for Commodore BASIC 3.5. |
||
< |
<syntaxhighlight lang="basic">1 REM ARCHIMEDEAN SPIRAL |
||
2 REM USING COMMODORE BASIC 7.0 |
2 REM USING COMMODORE BASIC 7.0 |
||
3 REM OF THE COMMODORE 128 |
3 REM OF THE COMMODORE 128 |
||
Line 262: | Line 634: | ||
90 X0 = X : Y0 = Y |
90 X0 = X : Y0 = Y |
||
100 NEXT T |
100 NEXT T |
||
110 GOTO 110</ |
110 GOTO 110</syntaxhighlight> |
||
==={{header|FreeBASIC}}=== |
==={{header|FreeBASIC}}=== |
||
< |
<syntaxhighlight lang="freebasic">' version 16-10-2016 |
||
' compile with: fbc -s gui |
' compile with: fbc -s gui |
||
Line 284: | Line 656: | ||
PSet(halfscrn + x, halfscrn - y), RGB(255, 255, 255) |
PSet(halfscrn + x, halfscrn - y), RGB(255, 255, 255) |
||
Next |
Next |
||
' empty keyboard buffer |
' empty keyboard buffer |
||
Line 290: | Line 661: | ||
Print : Print "hit any key to end program" |
Print : Print "hit any key to end program" |
||
Sleep |
Sleep |
||
End</ |
End</syntaxhighlight> |
||
==={{header|GW-BASIC}}=== |
|||
<syntaxhighlight lang="gwbasic">10 A = 0 |
|||
20 B = 1 |
|||
30 SCREEN 1 |
|||
40 FOR THETA = 0 TO 160 STEP .01 |
|||
50 R = A + B*THETA |
|||
60 X = R*COS(THETA) |
|||
70 Y = R*SIN(THETA) |
|||
80 PSET (160+X, 100-Y),3 |
|||
90 NEXT THETA |
|||
100 IF INKEY$="" THEN GOTO 100 |
|||
110 SCREEN 2:SCREEN 0 |
|||
120 END</syntaxhighlight> |
|||
==={{header|IS-BASIC}}=== |
==={{header|IS-BASIC}}=== |
||
< |
<syntaxhighlight lang="is-basic">100 GRAPHICS LORES 2 |
||
110 OPTION ANGLE DEGREES |
110 OPTION ANGLE DEGREES |
||
120 PLOT 640,360,ANGLE 90; |
120 PLOT 640,360,ANGLE 90; |
||
130 FOR I=2 TO 33.2 STEP .05 |
130 FOR I=2 TO 33.2 STEP .05 |
||
140 PLOT FORWARD I,LEFT 5; |
140 PLOT FORWARD I,LEFT 5; |
||
150 NEXT</ |
150 NEXT</syntaxhighlight> |
||
==={{header|Locomotive Basic}}=== |
|||
{{trans|Commodore BASIC}} |
|||
[[File:Cpcbasic spiral.png|thumb|Output]] |
|||
<syntaxhighlight lang="locobasic">10 a=1.5:b=2 |
|||
20 mode 2:rad:move 320,200 |
|||
30 for t=0 to 40*pi step 0.2 |
|||
40 r=a+b*t |
|||
50 draw r*sin(t)+320,r*cos(t)+200 |
|||
60 next |
|||
70 while inkey$="":wend</syntaxhighlight> |
|||
==={{header|PureBasic}}=== |
|||
<syntaxhighlight lang="purebasic">#MAXLOOP = 7*360 |
|||
#XCENTER = 640/2 |
|||
#YCENTER = 480/2 |
|||
#SCALAR = 200 |
|||
If OpenWindow(0, 100, 200, 640, 480, "Archimedean spiral") |
|||
If CreateImage(0, 640, 480,24,RGB(255,255,255)) |
|||
If StartDrawing(ImageOutput(0)) |
|||
i.f=0.0 |
|||
While i<=#MAXLOOP |
|||
x.f=#XCENTER+Cos(Radian(i))*#SCALAR*i/#MAXLOOP |
|||
y.f=#YCENTER+Sin(Radian(i))*#SCALAR*i/#MAXLOOP |
|||
Plot(x,y,RGB(50,50,50)) |
|||
i+0.05 |
|||
Wend |
|||
StopDrawing() |
|||
EndIf |
|||
EndIf |
|||
ImageGadget(0, 0, 0, 0, 0, ImageID(0)) |
|||
Repeat : Event = WaitWindowEvent() : Until Event = #PB_Event_CloseWindow |
|||
EndIf |
|||
End</syntaxhighlight> |
|||
==={{header|Run BASIC}}=== |
==={{header|Run BASIC}}=== |
||
< |
<syntaxhighlight lang="run basic"> 'archimedean spiral.bas |
||
'runs in Run Basic |
'runs in Run Basic |
||
'Run Basic website http://www.runbasic.com |
'Run Basic website http://www.runbasic.com |
||
Line 327: | Line 747: | ||
print "Thank you and Goodbye" |
print "Thank you and Goodbye" |
||
end |
end |
||
End</ |
End</syntaxhighlight> |
||
==={{header| |
==={{header|QBasic}}=== |
||
< |
<syntaxhighlight lang="qbasic">SCREEN 12 |
||
WINDOW (-2.67, -2!)-(2.67, 2!) |
WINDOW (-2.67, -2!)-(2.67, 2!) |
||
PI = 4 * ATN(1) |
PI = 4 * ATN(1) |
||
Line 341: | Line 761: | ||
Y = (A + B * T) * SIN(T) |
Y = (A + B * T) * SIN(T) |
||
LINE -(X, Y) |
LINE -(X, Y) |
||
NEXT</ |
NEXT</syntaxhighlight> |
||
==={{header|Sinclair ZX81 BASIC}}=== |
==={{header|Sinclair ZX81 BASIC}}=== |
||
{{trans|Applesoft BASIC}} |
{{trans|Applesoft BASIC}} |
||
Works with the unexpanded (1k RAM) ZX81. The output is quite blocky, but identifiably a spiral. |
Works with the unexpanded (1k RAM) ZX81. The output is quite blocky, but identifiably a spiral. |
||
< |
<syntaxhighlight lang="basic">10 LET A=1.5 |
||
20 LET B=0.7 |
20 LET B=0.7 |
||
30 FOR T=0 TO 7*PI STEP 0.05 |
30 FOR T=0 TO 7*PI STEP 0.05 |
||
40 LET R=A+B*T |
40 LET R=A+B*T |
||
50 PLOT R*COS T+32,R*SIN T+22 |
50 PLOT R*COS T+32,R*SIN T+22 |
||
60 NEXT T</ |
60 NEXT T</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Screenshot [http://edmundgriffiths.com/zx81archspiral.jpg here]. |
Screenshot [http://edmundgriffiths.com/zx81archspiral.jpg here]. |
||
==={{header|VBA}}=== |
|||
<syntaxhighlight lang="vb">Private Sub plot_coordinate_pairs(x As Variant, y As Variant) |
|||
Dim chrt As Chart |
|||
Set chrt = ActiveSheet.Shapes.AddChart.Chart |
|||
With chrt |
|||
.ChartType = xlXYScatter |
|||
.HasLegend = False |
|||
.SeriesCollection.NewSeries |
|||
.SeriesCollection.Item(1).XValues = x |
|||
.SeriesCollection.Item(1).Values = y |
|||
End With |
|||
End Sub |
|||
Public Sub main() |
|||
Dim x(1000) As Single, y(1000) As Single |
|||
a = 1 |
|||
b = 9 |
|||
For i = 0 To 1000 |
|||
theta = i * WorksheetFunction.Pi() / 60 |
|||
r = a + b * theta |
|||
x(i) = r * Cos(theta) |
|||
y(i) = r * Sin(theta) |
|||
Next i |
|||
plot_coordinate_pairs x, y |
|||
End Sub</syntaxhighlight> |
|||
==={{header|Yabasic}}=== |
|||
{{trans|Sinclair_ZX81_BASIC}} |
|||
<syntaxhighlight lang="yabasic">5 OPEN WINDOW 320, 200 : WINDOW ORIGIN "CC" |
|||
10 LET A=1.5 |
|||
20 LET B=0.7 |
|||
30 FOR T=0 TO 30*PI STEP 0.05 |
|||
40 LET R=A+B*T |
|||
50 LINE TO R*COS(T),R*SIN(T) |
|||
60 NEXT T</syntaxhighlight> |
|||
=={{header|BQN}}== |
|||
The BQN online REPL supports some basic plotting functionality through <code>•Plot</code>. This is used to create a spiral plotting function: |
|||
<syntaxhighlight lang="bqn">{(•math.Sin •Plot○(⊢×↕∘≠) •math.Cos) -(2×π) × 𝕩⥊(↕÷-⟜1)100}</syntaxhighlight> |
|||
When called with argument 200, it is similar to the given example diagram. |
|||
[https://mlochbaum.github.io/BQN/try.html#code=eyjigKJtYXRoLlNpbiDigKJQbG904peLKOKKosOX4oaV4oiY4omgKSDigKJtYXRoLkNvcykgLSgyw5fPgCkgw5cg8J2VqeKliijihpXDty3in5wxKTEwMH0yMDA= Try it out!] |
|||
=={{header|C}}== |
=={{header|C}}== |
||
Interactive code which asks the parameters a and b as inputs, the number of cycles and the division steps. Requires the [http://www.cs.colorado.edu/~main/bgi/cs1300/ WinBGIm] library. |
Interactive code which asks the parameters a and b as inputs, the number of cycles and the division steps. Requires the [http://www.cs.colorado.edu/~main/bgi/cs1300/ WinBGIm] library. |
||
<syntaxhighlight lang="c"> |
|||
<lang C> |
|||
#include<graphics.h> |
#include<graphics.h> |
||
#include<stdio.h> |
#include<stdio.h> |
||
Line 390: | Line 854: | ||
closegraph(); |
closegraph(); |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|C sharp|C#}}== |
|||
<syntaxhighlight lang="csharp">using System; |
|||
using System.Linq; |
|||
using System.Drawing; |
|||
using System.Diagnostics; |
|||
using System.Drawing.Drawing2D; |
|||
class Program |
|||
{ |
|||
const int width = 380; |
|||
const int height = 380; |
|||
static PointF archimedeanPoint(int degrees) |
|||
{ |
|||
const double a = 1; |
|||
const double b = 9; |
|||
double t = degrees * Math.PI / 180; |
|||
double r = a + b * t; |
|||
return new PointF { X = (float)(width / 2 + r * Math.Cos(t)), Y = (float)(height / 2 + r * Math.Sin(t)) }; |
|||
} |
|||
static void Main(string[] args) |
|||
{ |
|||
var bm = new Bitmap(width, height); |
|||
var g = Graphics.FromImage(bm); |
|||
g.SmoothingMode = SmoothingMode.AntiAlias; |
|||
g.FillRectangle(new SolidBrush(Color.White), new Rectangle { X = 0, Y = 0, Width = width, Height = height }); |
|||
var pen = new Pen(Color.OrangeRed, 1.5f); |
|||
var spiral = Enumerable.Range(0, 360 * 3).AsParallel().AsOrdered().Select(archimedeanPoint); |
|||
var p0 = new PointF(width / 2, height / 2); |
|||
foreach (var p1 in spiral) |
|||
{ |
|||
g.DrawLine(pen, p0, p1); |
|||
p0 = p1; |
|||
} |
|||
g.Save(); // is this really necessary ? |
|||
bm.Save("archimedes-csharp.png"); |
|||
Process.Start("archimedes-csharp.png"); // Launches default photo viewing app |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|C++}}== |
=={{header|C++}}== |
||
[[File:SpiralCpp.png|200px|thumb|right]] |
[[File:SpiralCpp.png|200px|thumb|right]] |
||
< |
<syntaxhighlight lang="cpp"> |
||
#include <windows.h> |
#include <windows.h> |
||
#include <string> |
#include <string> |
||
Line 505: | Line 1,012: | ||
spiral s; s.draw( 16, 8 ); return 0; |
spiral s; s.draw( 16, 8 ); return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header| |
=={{header|Clojure}}== |
||
{{Works with| Incanter}} |
|||
<syntaxhighlight lang="clojure"> |
|||
(use '(incanter core stats charts io)) |
|||
(defn Arquimidean-function |
|||
<lang csharp>using System; |
|||
[a b theta] |
|||
using System.Linq; |
|||
(+ a (* theta b))) |
|||
using System.Drawing; |
|||
using System.Diagnostics; |
|||
using System.Drawing.Drawing2D; |
|||
(defn transform-pl-xy [r theta] |
|||
class Program |
|||
(let [x (* r (sin theta)) |
|||
{ |
|||
y (* r (cos theta))] |
|||
const int width = 380; |
|||
[x y])) |
|||
const int height = 380; |
|||
static PointF archimedeanPoint(int degrees) |
|||
{ |
|||
const double a = 1; |
|||
const double b = 9; |
|||
double t = degrees * Math.PI / 180; |
|||
double r = a + b * t; |
|||
return new PointF { X = (float)(width / 2 + r * Math.Cos(t)), Y = (float)(height / 2 + r * Math.Sin(t)) }; |
|||
} |
|||
(defn arq-spiral [t] (transform-pl-xy (Arquimidean-function 0 7 t) t)) |
|||
static void Main(string[] args) |
|||
{ |
|||
var bm = new Bitmap(width, height); |
|||
var g = Graphics.FromImage(bm); |
|||
g.SmoothingMode = SmoothingMode.AntiAlias; |
|||
g.FillRectangle(new SolidBrush(Color.White), new Rectangle { X = 0, Y = 0, Width = width, Height = height }); |
|||
var pen = new Pen(Color.OrangeRed, 1.5f); |
|||
(view (parametric-plot arq-spiral 0 (* 10 Math/PI))) |
|||
var spiral = Enumerable.Range(0, 360 * 3).AsParallel().AsOrdered().Select(archimedeanPoint); |
|||
</syntaxhighlight> |
|||
var p0 = new PointF(width / 2, height / 2); |
|||
foreach (var p1 in spiral) |
|||
Another version inspired by the Java below, showing how to interop with awt/swing to do simple graphics: |
|||
{ |
|||
g.DrawLine(pen, p0, p1); |
|||
p0 = p1; |
|||
} |
|||
g.Save(); // is this really necessary ? |
|||
bm.Save("archimedes-csharp.png"); |
|||
Process.Start("archimedes-csharp.png"); // Launches default photo viewing app |
|||
} |
|||
} |
|||
</lang> |
|||
<syntaxhighlight lang="clojure"> |
|||
(let [panel (proxy [javax.swing.JPanel] [] |
|||
(paintComponent [g] |
|||
(proxy-super paintComponent g) |
|||
(.setStroke g (java.awt.BasicStroke. 2)) |
|||
(.setRenderingHint g java.awt.RenderingHints/KEY_ANTIALIASING |
|||
java.awt.RenderingHints/VALUE_ANTIALIAS_ON) |
|||
(let [[a b] [0 (/ 1 Math/PI)] |
|||
[w h] [(.getWidth this) (.getHeight this)] |
|||
[cx cy] [(/ w 2.0) (/ h 2.0)] |
|||
margin 16 |
|||
[rotations point-n] [3 (quot (min w h) 2)] |
|||
[ring-n line-n] [6 12] |
|||
scale (/ (- (min w h) (* 2 margin)) (* 2.0 ring-n))] |
|||
;; Grid |
|||
(.setColor g (java.awt.Color. 0xEEEEEE)) |
|||
(doseq [i (range 1 (inc ring-n))] |
|||
(let [[posx posy] [(- cx (* i scale)) (- cy (* i scale))]] |
|||
(.drawOval g posx posy (* 2 i scale) (* 2 i scale)))) |
|||
(dotimes [i line-n] |
|||
(let [theta (* 2 Math/PI (/ i (double line-n))) |
|||
[x y] [(+ cx (* scale ring-n (Math/cos theta))) |
|||
(+ cy (* scale ring-n (Math/sin theta)))]] |
|||
(.drawLine g cx cy x y))) |
|||
;; Spiral |
|||
(.setColor g (java.awt.Color. 0x202020)) |
|||
(loop [i 0 [x y] [(+ cx (* a scale)) cy]] |
|||
(let [p (/ (inc i) (double point-n)) |
|||
theta (* rotations 2 Math/PI p) |
|||
r (* scale (+ a (* b theta))) |
|||
[x1 y1] [(+ cx (* r (Math/cos theta))) |
|||
(- cy (* r (Math/sin theta)))]] |
|||
(.drawLine g x y x1 y1) |
|||
(when (< i (dec point-n)) (recur (inc i) [x1 y1])))))))] |
|||
(doto (javax.swing.JFrame.) |
|||
(.add (doto panel |
|||
(.setPreferredSize (java.awt.Dimension. 640 640)) |
|||
(.setBackground java.awt.Color/white)) |
|||
java.awt.BorderLayout/CENTER) |
|||
(.pack) |
|||
(.setVisible true))) |
|||
</syntaxhighlight> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
Line 555: | Line 1,082: | ||
Common Lisp doesn't provide native graphical output. Libraries or bitmapped output could be used instead, but for this solution, the output is accomplished with character printing. |
Common Lisp doesn't provide native graphical output. Libraries or bitmapped output could be used instead, but for this solution, the output is accomplished with character printing. |
||
< |
<syntaxhighlight lang="lisp">(defun draw-coords-as-text (coords size fill-char) |
||
(let* ((min-x (apply #'min (mapcar #'car coords))) |
(let* ((min-x (apply #'min (mapcar #'car coords))) |
||
(min-y (apply #'min (mapcar #'cdr coords))) |
(min-y (apply #'min (mapcar #'cdr coords))) |
||
Line 625: | Line 1,152: | ||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header| |
=={{header|Craft Basic}}== |
||
<syntaxhighlight lang="basic">bgcolor 0, 0, 0 |
|||
{{Works with| Incanter}} |
|||
cls graphics |
|||
<lang clojure> |
|||
fgcolor 255, 255, 0 |
|||
(use '(incanter core stats charts io)) |
|||
define pi = 3.14, size = 80 |
|||
(defn Arquimidean-function |
|||
define x = 250, y = 200 |
|||
[a b theta] |
|||
define a = 1.5, b = .7 |
|||
for t = 0 to size * pi step .1 |
|||
(defn transform-pl-xy [r theta] |
|||
(let [x (* r (sin theta)) |
|||
y (* r (cos theta))] |
|||
[x y])) |
|||
let r = a + b * t |
|||
(defn arq-spiral [t] (transform-pl-xy (Arquimidean-function 0 7 t) t)) |
|||
dot r * cos(t) + x, r * sin(t) + y |
|||
wait |
|||
next t</syntaxhighlight> |
|||
(view (parametric-plot arq-spiral 0 (* 10 Math/PI))) |
|||
=={{header|Delphi}}== |
|||
{{works with|Delphi|6.0}} |
|||
{{libheader|Types,ExtCtrls,Graphics}} |
|||
<syntaxhighlight lang="Delphi"> |
|||
procedure ArcSpiral(Image: TImage); |
|||
var Radius,Theta: double; |
|||
var X,Y: integer; |
|||
var Center: TPoint; |
|||
const Step = 0.2; |
|||
const Offset = 3; Spacing = 1.4; |
|||
begin |
|||
Image.Canvas.Brush.Color:=clWhite; |
|||
Image.Canvas.Rectangle(0,0,Image.Width,Image.Height); |
|||
Center:=Point(Image.Width div 2, Image.Height div 2); |
|||
Image.Canvas.MoveTo(Center.X,Center.Y); |
|||
Theta:=0; |
|||
while Theta<(40*Pi) do |
|||
begin |
|||
{Radius increases as theta increases} |
|||
Radius:=Offset+Spacing*Theta; |
|||
{Calculate position on circle} |
|||
X:=Trunc(Radius*Cos(Theta)+Center.X); |
|||
Y:=Trunc(Radius*sin(Theta)+Center.Y); |
|||
Image.Canvas.LineTo(X,Y); |
|||
Theta:=Theta+Step; |
|||
end; |
|||
end; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
[[File:DelphiASpiral.png|frame|none]] |
|||
<pre> |
|||
</pre> |
|||
=={{header|EasyLang}}== |
|||
[https://easylang.dev/show/#cod=JcwxCsAgEETRfk8xdQQRol08TSK4IAZUUG8f11TDg88kzqHz0yKMtjTg4QzNf3rkFFBwCQCk1S4euN+KBoWxVTlvTWkKlF9Xxgma4CRNHw== Run it] |
|||
<syntaxhighlight lang="easylang"> |
|||
linewidth 0.4 |
|||
x = 50 |
|||
y = 50 |
|||
while r < 50 |
|||
line r * cos t + x r * sin t + y |
|||
r += 0.05 |
|||
t += 3 |
|||
. |
|||
</syntaxhighlight> |
|||
=={{header|FOCAL}}== |
|||
<syntaxhighlight lang="focal">1.1 S A=1.5 |
|||
1.2 S B=2 |
|||
1.3 S N=250 |
|||
1.4 F T=1,N; D 2 |
|||
1.5 X FSKP(2*N) |
|||
1.6 Q |
|||
2.1 S R=A+B*T; D 3 |
|||
</lang> |
|||
2.2 X FPT(2*T,X1+512,Y1+390) |
|||
<pre> </pre> |
|||
2.3 S R=A+B*(T+1); D 4 |
|||
2.4 X FVEC(2*T+1,X2-X1,Y2-Y1) |
|||
3.1 S X1=R*FSIN(.2*T) |
|||
3.2 S Y1=R*FCOS(.2*T) |
|||
4.1 S X2=R*FSIN(.2*(T+1)) |
|||
4.2 S Y2=R*FCOS(.2*(T+1))</syntaxhighlight> |
|||
This program uses FOCAL-11 on a DEC GT40 vector graphics terminal. |
|||
=={{header|Frege}}== |
=={{header|Frege}}== |
||
Line 653: | Line 1,249: | ||
{{Works with|Frege|3.23.888}} |
{{Works with|Frege|3.23.888}} |
||
< |
<syntaxhighlight lang="frege">module Archimedean where |
||
import Java.IO |
import Java.IO |
||
Line 741: | Line 1,337: | ||
drawSpiral g |
drawSpiral g |
||
f <- File.new "SpiralFrege.png" |
f <- File.new "SpiralFrege.png" |
||
void $ ImageIO.write buffy "png" f</ |
void $ ImageIO.write buffy "png" f</syntaxhighlight> |
||
Output is [http://funwithsoftware.org/images/2016-SpiralFrege.png here] due to [[User talk:Short Circuit#Is file uploading blocked forever?|Is file uploading blocked forever?]] |
Output is [http://funwithsoftware.org/images/2016-SpiralFrege.png here] due to [[User talk:Short Circuit#Is file uploading blocked forever?|Is file uploading blocked forever?]] |
||
=={{header|Frink}}== |
|||
<syntaxhighlight lang="frink">p = new polyline |
|||
g = new graphics |
|||
a = 1 |
|||
b = 1 |
|||
for theta = 0 to 10 circle step 1 degree |
|||
{ |
|||
r = a + b theta |
|||
x = r cos[theta] |
|||
y = r sin[theta] |
|||
p.addPoint[x,-y] |
|||
} |
|||
g.add[p] |
|||
g.show[] |
|||
g.write["ArchimedeanSpiralFrink.svg",800,800]</syntaxhighlight> |
|||
[[File:ArchimedeanSpiralFrink.svg|400 px]] |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
_maxPoints = 190 |
|||
void local fn DoIt |
|||
window 1, @"Archimedean Spiral", (0,0,500,500) |
|||
WindowSetBackgroundColor( 1, fn ColorBlack ) |
|||
pen 3, fn ColorRed |
|||
float x, y, angle |
|||
long i, a = 10, b = 10, x1 = 250, y1 = 250 |
|||
for i = 0 to _maxPoints - 1 |
|||
angle = 0.1 * i |
|||
x = (a + b * angle) * cos(angle) + 250 |
|||
y = (a + b * angle) * sin(angle) + 250 |
|||
line x1,y1 to x,y |
|||
x1 = x : y1 = y |
|||
next |
|||
end fn |
|||
fn DoIt |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
[[File:ArchimedeanSpiralFB.png]] |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
{{works with|go|1.9}} |
{{works with|go|1.9}} |
||
Creates a PNG file using only built-in packages. |
Creates a PNG file using only built-in packages. |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 795: | Line 1,437: | ||
log.Fatal(err) |
log.Fatal(err) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
Line 802: | Line 1,444: | ||
{{libheader|Juicy.Pixels}} |
{{libheader|Juicy.Pixels}} |
||
{{libheader|Rasterific}} |
{{libheader|Rasterific}} |
||
< |
<syntaxhighlight lang="haskell">#!/usr/bin/env stack |
||
-- stack --resolver lts-7.0 --install-ghc runghc --package Rasterific --package JuicyPixels |
-- stack --resolver lts-7.0 --install-ghc runghc --package Rasterific --package JuicyPixels |
||
Line 828: | Line 1,470: | ||
polyline points |
polyline points |
||
writePng "SpiralHaskell.png" img</ |
writePng "SpiralHaskell.png" img</syntaxhighlight> |
||
Output is [http://funwithsoftware.org/images/2016-SpiralHaskell.png here] due to [[User talk:Short Circuit#Is file uploading blocked forever?|Is file uploading blocked forever?]] |
Output is [http://funwithsoftware.org/images/2016-SpiralHaskell.png here] due to [[User talk:Short Circuit#Is file uploading blocked forever?|Is file uploading blocked forever?]] |
||
Line 834: | Line 1,476: | ||
=={{header|J}}== |
=={{header|J}}== |
||
[[File:Archimedian spiral j.png|200px|thumb|right]] |
[[File:Archimedian spiral j.png|200px|thumb|right]] |
||
< |
<syntaxhighlight lang="j">require'plot' |
||
'aspect 1' plot (*^)j.0.01*i.1400</ |
'aspect 1' plot (*^)j.0.01*i.1400</syntaxhighlight> |
||
<div style="clear:both"></div> |
<div style="clear:both"></div> |
||
Line 842: | Line 1,484: | ||
[[File:archimedian_spiral.png|300px|thumb|right]] |
[[File:archimedian_spiral.png|300px|thumb|right]] |
||
{{works with|Java|8}} |
{{works with|Java|8}} |
||
< |
<syntaxhighlight lang="java">import java.awt.*; |
||
import static java.lang.Math.*; |
import static java.lang.Math.*; |
||
import javax.swing.*; |
import javax.swing.*; |
||
Line 925: | Line 1,567: | ||
}); |
}); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
===ES5=== |
|||
{{Works with|Chrome}} |
{{Works with|Chrome}} |
||
[[File:ASjs.png|200px|right|thumb|Output ASjs.png]] |
[[File:ASjs.png|200px|right|thumb|Output ASjs.png]] |
||
< |
<syntaxhighlight lang="html"> |
||
<!-- ArchiSpiral.html --> |
<!-- ArchiSpiral.html --> |
||
<html> |
<html> |
||
Line 955: | Line 1,598: | ||
} |
} |
||
</script></body></html> |
</script></body></html> |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Output}} |
{{Output}} |
||
<pre> |
<pre> |
||
Line 961: | Line 1,604: | ||
spiral as a png-file, for example. |
spiral as a png-file, for example. |
||
</pre> |
</pre> |
||
===ES6=== |
|||
Assumes the same HTML canvas embedding as above, but is functionally composed. |
|||
Defines and logs a set of points, before rendering them to canvas. |
|||
<syntaxhighlight lang="html"><html> |
|||
<head> |
|||
<title>Archimedean spiral</title> |
|||
<style>h3 {font-family:sans-serif; color:gray;}</style> |
|||
</head> |
|||
<body onload="main('red')(15)"> |
|||
<h3>Archimedean spiral</h3></p> |
|||
<canvas id="spiral" width="640" height="640" style="border: 2px outset;"></canvas> |
|||
<script></syntaxhighlight> |
|||
<syntaxhighlight lang="javascript">const main = strColor => intCycles => { |
|||
const |
|||
ai = 0.05, |
|||
ri = 0.1, |
|||
cvs = document.getElementById('spiral'), |
|||
ctx = cvs.getContext('2d'), |
|||
s = cvs.width / 2, |
|||
points = enumFromTo(1)( |
|||
Math.PI * 2 * intCycles / ai |
|||
).map(i => [Math.cos, Math.sin].map( |
|||
f => ri * i * f(ai * i) + s |
|||
)); |
|||
return ( |
|||
console.log(points), |
|||
ctx.fillStyle = 'white', |
|||
ctx.fillRect(0, 0, cvs.width, cvs.height), |
|||
ctx.beginPath(), |
|||
points.forEach(xy => ctx.lineTo(...xy)), |
|||
ctx.strokeStyle = strColor, |
|||
ctx.stroke(), |
|||
points |
|||
); |
|||
}; |
|||
// enumFromTo :: Int -> Int -> [Int] |
|||
const enumFromTo = m => n => |
|||
Array.from({ |
|||
length: 1 + n - m |
|||
}, (_, i) => m + i);</syntaxhighlight> |
|||
<syntaxhighlight lang="html"></script></body></html></syntaxhighlight> |
|||
=={{header|jq}}== |
|||
{{works with|jq}} |
|||
'''Works with gojq, the Go implementation of jq''' |
|||
====SVG version==== |
|||
<syntaxhighlight lang="jq">def spiral($zero; $turns; $step): |
|||
def pi: 1 | atan * 4; |
|||
def p2: (. * 100 | round) / 100; |
|||
def svg: |
|||
400 as $width |
|||
| 400 as $height |
|||
| 2 as $swidth # stroke |
|||
| "blue" as $stroke |
|||
| (range($zero; $turns * 2 * pi; $step) as $theta |
|||
| (((($theta)|cos) * 2 * $theta + ($width/2)) |p2) as $x |
|||
| (((($theta)|sin) * 2 * $theta + ($height/2))|p2) as $y |
|||
| if $theta == $zero |
|||
then "<path fill='transparent' style='stroke:\($stroke); stroke-width:\($swidth)' d='M \($x) \($y)" |
|||
else " L \($x) \($y)" |
|||
end), |
|||
"' />"; |
|||
"<svg width='100%' height='100%' |
|||
xmlns='http://www.w3.org/2000/svg'>", |
|||
svg, |
|||
"</svg>" ; |
|||
spiral(0; 10; 0.025) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
[https://ibb.co/kMSDzx1 PNG version of SVG file] |
|||
(Please feel free to upload to RC) |
|||
====ASCII Art Version==== |
|||
{{trans|awk}} |
|||
<syntaxhighlight lang="jq">def spiral($a; $b; $step; $h): |
|||
def min($x;$y): if $x <= $y then $x else $y end; |
|||
def max($x;$y): if $x <= $y then $y else $x end; |
|||
def pi: 1 | atan * 4; |
|||
(6 * pi) as $m |
|||
| ($h * 1.5) as $w |
|||
| { x_min: 9999, y_min: 9999, |
|||
x_max: 0, y_max: 0, |
|||
arr: [] } |
|||
| reduce range($step; $m+$step; $step) as $t (.; |
|||
.r = $a + $b * $t |
|||
| ((.r * ($t|cos) + $w) | round) as $x |
|||
| ((.r * ($t|sin) + $h) | round) as $y |
|||
| if $x <= 0 or $y <= 0 then . |
|||
elif $x >= 280 then . |
|||
elif $y >= 192 then . |
|||
else .arr[$x][$y] = "*" |
|||
| .x_min = min(.x_min; $x) |
|||
| .x_max = max(.x_max; $x) |
|||
| .y_min = min(.y_min; $y) |
|||
| .y_max = max(.y_max; $y) |
|||
end ) |
|||
# ... and print it |
|||
| .arr as $arr |
|||
| range(.x_min; .x_max + 1) as $i |
|||
| reduce range(.y_min; .y_max+1) as $j ( ""; |
|||
. + ($arr[$i][$j] // " ") ) |
|||
| "\(.)\n" ; |
|||
spiral(1; 1; 0.02; 96)</syntaxhighlight> |
|||
{{out}} |
|||
As for [[#awk|awk]]. |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
{{works with|Julia|0.6}} |
{{works with|Julia|0.6}} |
||
< |
<syntaxhighlight lang="julia">using UnicodePlots |
||
spiral(θ, a=0, b=1) = @. b * θ * cos(θ + a), b * θ * sin(θ + a) |
spiral(θ, a=0, b=1) = @. b * θ * cos(θ + a), b * θ * sin(θ + a) |
||
x, y = spiral(1:0.1:10) |
x, y = spiral(1:0.1:10) |
||
println(lineplot(x, y))</ |
println(lineplot(x, y))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 995: | Line 1,756: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="scala">// version 1.1.0 |
||
import java.awt.* |
import java.awt.* |
||
Line 1,070: | Line 1,831: | ||
f.isVisible = true |
f.isVisible = true |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Lambdatalk}}== |
|||
<syntaxhighlight lang="Scheme"> |
|||
1) from polar to cartesian coordinates |
|||
x = r*cos(t) = (a+b*t)*cos(t) |
|||
y = r*sin(t) = (a+b*t)*sin(t) |
|||
2) define the curve |
|||
{def CURVE |
|||
{lambda {:a :b :t} |
|||
{* {+ :a {* :b :t}} {cos :t}} |
|||
{* {+ :a {* :b :t}} {sin :t}} |
|||
}} |
|||
-> CURVE |
|||
3) and draw it using SVG |
|||
{{SVG 580} |
|||
{g {AXES 580 580} |
|||
{polyline {@ points="{S.map {CURVE 5 4} |
|||
{S.serie 0 {* 10 {PI}} 0.1}}" |
|||
{stroke red 3}} |
|||
}}} |
|||
</syntaxhighlight> |
|||
The ouput can be seen in http://lambdaway.free.fr/lambdawalks/?view=archimedian_spiral |
|||
=={{header|Lua}}== |
|||
{{libheader|LÖVE}} |
|||
{{works with|LÖVE|11.3}} |
|||
<syntaxhighlight lang="lua"> |
|||
a=1 |
|||
b=2 |
|||
cycles=40 |
|||
step=0.001 |
|||
x=0 |
|||
y=0 |
|||
function love.load() |
|||
x = love.graphics.getWidth()/2 |
|||
y = love.graphics.getHeight()/2 |
|||
end |
|||
function love.draw() |
|||
love.graphics.print("a="..a,16,16) |
|||
love.graphics.print("b="..b,16,32) |
|||
for i=0,cycles*math.pi,step do |
|||
love.graphics.points(x+(a + b*i)*math.cos(i),y+(a + b*i)*math.sin(i)) |
|||
end |
|||
end |
|||
</syntaxhighlight> |
|||
=={{header|M2000 Interpreter}}== |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
module Archimedean_spiral { |
|||
smooth on ' enable GDI+ |
|||
def r(θ)=5+3*θ |
|||
cls #002222,0 |
|||
pen #FFFF00 |
|||
refresh 5000 |
|||
every 1000 { |
|||
\\ redifine window (console width and height) and place it to center (symbol ;) |
|||
Window 12, random(10, 18)*1000, random(8, 12)*1000; |
|||
move scale.x/2, scale.y/2 |
|||
let N=2, k1=pi/120, k=k1, op=5, op1=1 |
|||
for i=1 to int(1200*min.data(scale.x, scale.y)/18000) |
|||
pen op |
|||
swap op, op1 |
|||
Width 3 {draw angle k, r(k)*n} |
|||
k+=k1 |
|||
next |
|||
refresh 5000 |
|||
\\ press space to exit loop |
|||
if keypress(32) then exit |
|||
} |
|||
pen 14 |
|||
cls 5 |
|||
refresh 50 |
|||
} |
|||
Archimedean_spiral |
|||
</syntaxhighlight> |
|||
=={{header|Maple}}== |
=={{header|Maple}}== |
||
<syntaxhighlight lang="maple"> |
|||
<lang Maple> |
|||
plots[polarplot](1+2*theta, theta = 0 .. 6*Pi) |
plots[polarplot](1+2*theta, theta = 0 .. 6*Pi) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Mathematica}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
The built-in function PolarPlot easily creates the desired plot |
The built-in function PolarPlot easily creates the desired plot |
||
< |
<syntaxhighlight lang="mathematica">With[{a = 5, b = 4}, PolarPlot[a + b t, {t, 0, 10 Pi}]]</syntaxhighlight> |
||
=={{header|MATLAB}}== |
=={{header|MATLAB}}== |
||
< |
<syntaxhighlight lang="matlab">a = 1; |
||
b = 1; |
b = 1; |
||
turns = 2; |
turns = 2; |
||
theta = 0:0.1:2*turns*pi; |
theta = 0:0.1:2*turns*pi; |
||
polarplot(theta, a + b*theta);</ |
polarplot(theta, a + b*theta);</syntaxhighlight> |
||
=={{header|Maxima}}== |
|||
Using draw package |
|||
<syntaxhighlight lang="maxima"> |
|||
archi_spi(a,b):=wxdraw2d(nticks=200,polar(a+b*theta,theta,1,10*%pi))$ |
|||
archi_spi(1,1); |
|||
</syntaxhighlight> |
|||
[[File:Archi spi.png|thumb|center]] |
|||
=={{header|MiniScript}}== |
|||
For use with the [http://miniscript.org/MiniMicro Mini Micro]. |
|||
<syntaxhighlight lang="miniscript"> |
|||
clear |
|||
x0 = gfx.width / 2 |
|||
y0 = gfx.height / 2 |
|||
gfx.clear color.white |
|||
for t in range(0, 70 * pi, 0.1) |
|||
r = 3.2+ 1.5 * t |
|||
x = r * cos(t) + gfx.width / 2 |
|||
y = r * sin(t) + gfx.height / 2 |
|||
gfx.line x0, y0, x, y, color.black,2 |
|||
x0 = x; y0 = y |
|||
end for |
|||
</syntaxhighlight> |
|||
Alternative version using a Turtle library included with the [http://miniscript.org/MiniMicro Mini Micro]. |
|||
<syntaxhighlight lang="miniscript"> |
|||
import "turtle" |
|||
radToDegrees = function(rad) |
|||
return 180 * rad / pi |
|||
end function |
|||
clear |
|||
print Turtle.displayNum |
|||
display(Turtle.displayNum).clear |
|||
t = new Turtle |
|||
for i in range(0, 50, 0.04) |
|||
t.forward i |
|||
t.left radToDegrees(pi/20) |
|||
end for |
|||
</syntaxhighlight> |
|||
=={{header|Nim}}== |
|||
{{libheader|gintro}} |
|||
<syntaxhighlight lang="nim">import math |
|||
import gintro/[glib, gobject, gtk, gio, cairo] |
|||
const |
|||
Width = 601 |
|||
Height = 601 |
|||
Limit = 12 * math.PI |
|||
Origin = (x: float(Width div 2), y: float(Height div 2)) |
|||
B = floor((Width div 2) / Limit) |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc draw(area: DrawingArea; context: Context) = |
|||
## Draw the spiral. |
|||
var theta = 0.0 |
|||
var delta = 0.01 |
|||
var (prevx, prevy) = Origin |
|||
# Clear the region. |
|||
context.moveTo(0, 0) |
|||
context.setSource(0.0, 0.0, 0.0) |
|||
context.paint() |
|||
# Draw the spiral. |
|||
context.setSource(1.0, 1.0, 0.0) |
|||
context.moveTo(Origin.x, Origin.y) |
|||
while theta < Limit: |
|||
let r = B * theta |
|||
let x = Origin.x + r * cos(theta) # X-coordinate on drawing area. |
|||
let y = Origin.y + r * sin(theta) # Y-coordinate on drawing area. |
|||
context.lineTo(x, y) |
|||
context.stroke() |
|||
# Set data for next round. |
|||
context.moveTo(x, y) |
|||
prevx = x |
|||
prevy = y |
|||
theta += delta |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc onDraw(area: DrawingArea; context: Context; data: pointer): bool = |
|||
## Callback to draw/redraw the drawing area contents. |
|||
area.draw(context) |
|||
result = true |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc activate(app: Application) = |
|||
## Activate the application. |
|||
let window = app.newApplicationWindow() |
|||
window.setSizeRequest(Width, Height) |
|||
window.setTitle("Archimedean spiral") |
|||
# Create the drawing area. |
|||
let area = newDrawingArea() |
|||
window.add(area) |
|||
# Connect the "draw" event to the callback to draw the spiral. |
|||
discard area.connect("draw", ondraw, pointer(nil)) |
|||
window.showAll() |
|||
#——————————————————————————————————————————————————————————————————————————————————————————————————— |
|||
let app = newApplication(Application, "Rosetta.spiral") |
|||
discard app.connect("activate", activate) |
|||
discard app.run()</syntaxhighlight> |
|||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Line 1,094: | Line 2,058: | ||
[[File:ArchiSpiral2.png|right|thumb|Output ArchiSpiral2.png]] |
[[File:ArchiSpiral2.png|right|thumb|Output ArchiSpiral2.png]] |
||
< |
<syntaxhighlight lang="parigp"> |
||
\\ The Archimedean spiral |
\\ The Archimedean spiral |
||
\\ ArchiSpiral() - Where: lps is a number of loops, c is a direction 0/1 |
\\ ArchiSpiral() - Where: lps is a number of loops, c is a direction 0/1 |
||
Line 1,114: | Line 2,078: | ||
ArchiSpiral(640,5,1); \\ArchiSpiral2.png |
ArchiSpiral(640,5,1); \\ArchiSpiral2.png |
||
} |
} |
||
</ |
</syntaxhighlight> |
||
{{Output}} |
{{Output}} |
||
Line 1,124: | Line 2,088: | ||
*** The Archimedean spiral: size=640 loops=5 c=1 |
*** The Archimedean spiral: size=640 loops=5 c=1 |
||
</pre> |
</pre> |
||
=={{header|PascalABC.NET}}== |
|||
[[File:Arch1.png|200px|thumb|right|Arch spiral PascalABC.NET]] |
|||
<syntaxhighlight lang="delphi"> |
|||
uses PlotWPF,GraphWPF; |
|||
begin |
|||
Window.SetSize(600,600); |
|||
var seq := Range(0,20,0.1); |
|||
var xx := seq.Select(t -> t * Cos(t)); |
|||
var yy := seq.Select(t -> t * Sin(t)); |
|||
LineGraphWPF.Create(xx,yy,Colors.Black); |
|||
end. |
|||
</syntaxhighlight> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
{{trans| |
{{trans|Raku}} |
||
< |
<syntaxhighlight lang="perl">use Imager; |
||
use constant PI => 3.14159265; |
use constant PI => 3.14159265; |
||
Line 1,140: | Line 2,122: | ||
$img->write(file => 'Archimedean-spiral.png'); |
$img->write(file => 'Archimedean-spiral.png'); |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header| |
=={{header|Phix}}== |
||
{{trans|zkl}} |
|||
{{works with|Rakudo|2018.10}} |
|||
{{libheader|Phix/pGUI}} |
|||
{{libheader|Phix/online}} |
|||
You can run this online [http://phix.x10.mx/p2js/Archimedean_spiral.htm here]. |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
-- demo\rosetta\Archimedean_spiral.exw |
|||
-- =================================== |
|||
--</span> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> |
|||
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span> |
|||
<span style="color: #004080;">cdCanvas</span> <span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">cy</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">deg</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">360</span><span style="color: #0000FF;">*</span><span style="color: #000000;">7</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">rad</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deg</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rad</span><span style="color: #0000FF;">*</span><span style="color: #000000;">b</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">a</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cx</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rad</span><span style="color: #0000FF;">)),</span> |
|||
<span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cy</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rad</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #7060A8;">cdCanvasPixel</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">#00FF00</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">map_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_WHITE</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_RED</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupCanvas</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"RASTERSIZE=500x500"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- initial size</span> |
|||
<span style="color: #7060A8;">IupSetCallbacks</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"MAP_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"map_cb"</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #008000;">"ACTION"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">)})</span> |
|||
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`TITLE="Archimedean spiral"`</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- release the minimum limitation</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
|||
<!--</syntaxhighlight>--> |
|||
=={{header|Processing}}== |
|||
<lang perl6>use Image::PNG::Portable; |
|||
Processing examples are animated, with a new point / segment added each draw() frame. Because Processing includes multiple built-in ways for drawing in rotating frames of reference, there are several ways to approach the Archimedean spiral problem. |
|||
===Java mode=== |
|||
my ($w, $h) = (400, 400); |
|||
====with points==== |
|||
When drawn with points the rotation must be very small, and initially the animation is very slow. This is because the points will move further and further apart as the radius increases. |
|||
<syntaxhighlight lang="processing">float x, y; |
|||
float theta; |
|||
float rotation; |
|||
void setup() { |
|||
my $png = Image::PNG::Portable.new: :width($w), :height($h); |
|||
size(300, 300); |
|||
theta = 0; |
|||
(0, .025 ... 52*π).race.map: -> \Θ { |
|||
rotation = 0.1; |
|||
$png.set: |((cis( Θ / π ) * Θ).reals »+« ($w/2, $h/2))».Int, 255, 0, 255; |
|||
background(255); |
|||
} |
} |
||
void draw() { |
|||
$png.write: 'Archimedean-spiral-perl6.png';</lang> |
|||
translate(width/2.0, height/2.0); |
|||
x = theta*cos(theta/PI); |
|||
y = theta*sin(theta/PI); |
|||
point(x, y); |
|||
theta = theta + rotation; |
|||
// check restart |
|||
if (x>width/2.0) frameCount=-1; |
|||
}</syntaxhighlight> |
|||
====with points, rotated==== |
|||
=={{header|Phix}}== |
|||
Rotates the canvas matrix using the built-in rotate() and draws a simple point, rather than computing rotated coordinates with sin()/cos(). |
|||
{{trans|zkl}} |
|||
<syntaxhighlight lang="processing">float theta; |
|||
{{libheader|pGUI}} |
|||
float rotation; |
|||
<lang Phix>-- |
|||
-- demo\rosetta\Archimedean_spiral.exw |
|||
-- |
|||
include pGUI.e |
|||
void setup() { |
|||
Ihandle dlg, canvas |
|||
size(300, 300); |
|||
cdCanvas cddbuffer, cdcanvas |
|||
theta = 0; |
|||
rotation = 0.1; |
|||
background(255); |
|||
} |
|||
void draw() { |
|||
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/) |
|||
translate(width/2.0, height/2.0); |
|||
integer a = 0, b = 5 |
|||
theta += rotation; |
|||
integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE") |
|||
rotate(theta/PI); |
|||
integer {centerX,centerY} = sq_floor_div({width,height},2) |
|||
point(theta, 0); |
|||
cdCanvasActivate(cddbuffer) |
|||
// check restart |
|||
for deg=0 to 360*7 do |
|||
if (theta>width/2.0) frameCount=-1; |
|||
atom rad = deg*PI/180 |
|||
}</syntaxhighlight> |
|||
atom r = rad*b + a |
|||
integer x = centerX + floor(r*cos(rad)) |
|||
integer y = centerY + floor(r*sin(rad)) |
|||
cdCanvasPixel(cddbuffer, x, y, #00FF00) |
|||
end for |
|||
cdCanvasFlush(cddbuffer) |
|||
return IUP_DEFAULT |
|||
end function |
|||
====with points, vector==== |
|||
function map_cb(Ihandle ih) |
|||
Rotates a vector object of increasing magnitude using the built-in PVector and draws its point, rather than computing rotated coordinates with sin()/cos(). |
|||
cdcanvas = cdCreateCanvas(CD_IUP, ih) |
|||
<syntaxhighlight lang="processing">PVector pv; |
|||
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas) |
|||
float rotation; |
|||
cdCanvasSetBackground(cddbuffer, CD_WHITE) |
|||
cdCanvasSetForeground(cddbuffer, CD_RED) |
|||
return IUP_DEFAULT |
|||
end function |
|||
void setup() { |
|||
function esc_close(Ihandle /*ih*/, atom c) |
|||
size(300, 300); |
|||
if c=K_ESC then return IUP_CLOSE end if |
|||
rotation = 0.1; |
|||
return IUP_CONTINUE |
|||
pv = new PVector(rotation, 0); |
|||
end function |
|||
background(255); |
|||
} |
|||
void draw() { |
|||
procedure main() |
|||
translate(width/2.0, height/2.0); |
|||
IupOpen() |
|||
pv.setMag(pv.mag()+rotation); |
|||
println(pv.mag()); |
|||
pv.rotate(rotation/PI); |
|||
point(pv.x, pv.y); |
|||
// check restart |
|||
if (pv.mag()>width/2.0) frameCount=-1; |
|||
}</syntaxhighlight> |
|||
====with line segments==== |
|||
canvas = IupCanvas(NULL) |
|||
Draw each new line segments anchored to the previous point in order to keep the spiral visually connected no matter how much the radius expands. |
|||
IupSetAttribute(canvas, "RASTERSIZE", "340x340") -- initial size |
|||
<syntaxhighlight lang="processing">float px, py, x, y; |
|||
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb")) |
|||
float theta; |
|||
float rotation; |
|||
void setup() { |
|||
dlg = IupDialog(canvas) |
|||
size(300, 300); |
|||
IupSetAttribute(dlg, "TITLE", "Archimedean spiral") |
|||
px = py = x = y = theta = 0; |
|||
IupSetCallback(dlg, "K_ANY", Icallback("esc_close")) |
|||
rotation = 0.1; |
|||
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb")) |
|||
background(255); |
|||
} |
|||
void draw() { |
|||
IupMap(dlg) |
|||
translate(width/2.0, height/2.0); |
|||
IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation |
|||
x = theta*cos(theta/PI); |
|||
IupShowXY(dlg,IUP_CENTER,IUP_CENTER) |
|||
y = (theta)*sin(theta/PI); |
|||
IupMainLoop() |
|||
line(x, y, px, py); |
|||
theta = theta + rotation; |
|||
end procedure |
|||
px = x; |
|||
py = y; |
|||
// check restart |
|||
if (px>width/2.0) frameCount=-1; |
|||
}</syntaxhighlight> |
|||
====with line segments, rotated==== |
|||
main()</lang> |
|||
Uses the built-in rotate() and screenX() to rotate the frame of reference and then recover the rotated screen position of each next point. Draw each new line segments anchored to the previous point in order to keep the spiral visually connected no matter how much the radius expands. |
|||
<syntaxhighlight lang="processing">float x, y, px, py; |
|||
float theta; |
|||
float rotation; |
|||
void setup() { |
|||
=={{header|Processing}}== |
|||
size(300, 300); |
|||
<lang java>float x, y, theta; |
|||
x = y = px = py = theta = 0; |
|||
void setup() |
|||
rotation = 0.1; |
|||
{ |
|||
background(255); |
|||
theta = 0; |
|||
size(500,500); |
|||
} |
} |
||
void draw() |
void draw() { |
||
// find coordinates with rotating reference frame |
|||
{ |
|||
pushMatrix(); |
|||
x = (width/2)+theta*cos(theta/PI); |
|||
rotate(theta/PI); |
|||
x = screenX(theta, 0); |
|||
point(x,y); |
|||
y = screenY(theta, 0); |
|||
popMatrix(); |
|||
}</lang> |
|||
translate(width/2.0, height/2.0); |
|||
theta += rotation; |
|||
line(px, py, x, y); |
|||
px = x; |
|||
py = y; |
|||
if (theta>width/2.0) frameCount=-1; // start over |
|||
}</syntaxhighlight> |
|||
=={{header| |
==={{header|Processing Python mode}}=== |
||
====with points==== |
|||
<lang PureBasic>#MAXLOOP = 7*360 |
|||
When drawn with points the rotation must be very small, and initially the animation is very slow. This is because the points will move further and further apart as the radius increases. |
|||
#XCENTER = 640/2 |
|||
<syntaxhighlight lang="python">theta = 0 |
|||
#YCENTER = 480/2 |
|||
rotation = 0.1 |
|||
#SCALAR = 200 |
|||
def setup(): |
|||
If OpenWindow(0, 100, 200, 640, 480, "Archimedean spiral") |
|||
size(300, 300) |
|||
If CreateImage(0, 640, 480,24,RGB(255,255,255)) |
|||
background(255) |
|||
If StartDrawing(ImageOutput(0)) |
|||
i.f=0.0 |
|||
def draw(): |
|||
While i<=#MAXLOOP |
|||
global theta |
|||
x.f=#XCENTER+Cos(Radian(i))*#SCALAR*i/#MAXLOOP |
|||
translate(width / 2.0, height / 2.0) |
|||
y.f=#YCENTER+Sin(Radian(i))*#SCALAR*i/#MAXLOOP |
|||
x = theta * cos(theta / PI) |
|||
y = theta * sin(theta / PI) |
|||
point(x, y) |
|||
theta = theta + rotation |
|||
# check restart |
|||
if x > width / 2.0: |
|||
EndIf |
|||
background(255) |
|||
ImageGadget(0, 0, 0, 0, 0, ImageID(0)) |
|||
theta = 0</syntaxhighlight> |
|||
Repeat : Event = WaitWindowEvent() : Until Event = #PB_Event_CloseWindow |
|||
EndIf |
|||
End</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
Using the '''turtle''' module. |
Using the '''turtle''' module. |
||
< |
<syntaxhighlight lang="python">from turtle import * |
||
from math import * |
from math import * |
||
color("blue") |
color("blue") |
||
Line 1,272: | Line 2,338: | ||
goto(x, y) |
goto(x, y) |
||
up() |
up() |
||
done()</ |
done()</syntaxhighlight> |
||
=={{header|Quackery}}== |
|||
<syntaxhighlight lang="quackery"> [ $ "turtleduck.qky" loadfile ] now! |
|||
turtle |
|||
20 frames |
|||
0 n->v |
|||
900 times |
|||
[ 2dup walk |
|||
1 20 v+ |
|||
1 36 turn ] |
|||
2drop |
|||
1 frames</syntaxhighlight> |
|||
{{out}} |
|||
[[File:Quackery Archimedean spiral.png]] |
|||
=={{header|R}}== |
=={{header|R}}== |
||
< |
<syntaxhighlight lang="r">with(list(s=seq(0, 10 * pi, length.out=500)), |
||
plot((1 + s) * exp(1i * s), type="l"))</ |
plot((1 + s) * exp(1i * s), type="l"))</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
[[File:archemedian-spiral-racket.png]] |
[[File:archemedian-spiral-racket.png]] |
||
< |
<syntaxhighlight lang="racket">#lang racket/base |
||
(require plot |
(require plot |
||
racket/math) |
racket/math) |
||
Line 1,302: | Line 2,384: | ||
;; writes to a file so hopefully, I can post it to RC... |
;; writes to a file so hopefully, I can post it to RC... |
||
(plot-file (list (archemedian-spiral-renderer2d 0.0 24 4)) |
(plot-file (list (archemedian-spiral-renderer2d 0.0 24 4)) |
||
"images/archemidian-spiral-racket.png")</ |
"images/archemidian-spiral-racket.png")</syntaxhighlight> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|2018.10}} |
|||
<syntaxhighlight lang="raku" line>use Image::PNG::Portable; |
|||
my ($w, $h) = (400, 400); |
|||
my $png = Image::PNG::Portable.new: :width($w), :height($h); |
|||
(0, .025 ... 52*π).race.map: -> \Θ { |
|||
$png.set: |((cis( Θ / π ) * Θ).reals »+« ($w/2, $h/2))».Int, 255, 0, 255; |
|||
} |
|||
$png.write: 'Archimedean-spiral-perl6.png';</syntaxhighlight> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
Line 1,308: | Line 2,406: | ||
Note: the value of <big><big> ''a'' </big></big> doesn't mean that much as the plot is automatically centered. |
Note: the value of <big><big> ''a'' </big></big> doesn't mean that much as the plot is automatically centered. |
||
< |
<syntaxhighlight lang="rexx">/*REXX pgm plots several cycles (half a spiral) of the Archimedean spiral (ASCII plot).*/ |
||
parse arg cy a b inc chr . /*obtain optional arguments from the CL*/ |
parse arg cy a b inc chr . /*obtain optional arguments from the CL*/ |
||
if cy=='' | cy=="," then cy= 3 /*Not specified? Then use the default.*/ |
if cy=='' | cy=="," then cy= 3 /*Not specified? Then use the default.*/ |
||
Line 1,327: | Line 2,425: | ||
y= h + r*sin(t); yy= y % 2 /* " " " Y " " */ |
y= h + r*sin(t); yy= y % 2 /* " " " Y " " */ |
||
if x<0 | y<0 | x>mw | y>mh then iterate /*Is X or Y out of bounds? Then skip.*/ |
if x<0 | y<0 | x>mw | y>mh then iterate /*Is X or Y out of bounds? Then skip.*/ |
||
if LOx==. then do; LOx=xx; HIx=xx; LOy=yy; HIy=yy |
if LOx==. then do; LOx= xx; HIx= xx; LOy= yy; HIy= yy |
||
end /* [↑] find the minimums and maximums.*/ |
end /* [↑] find the minimums and maximums.*/ |
||
LOx= min(LOx, xx); HIx= max(HIx, xx) /*determine the X MIN and MAX. */ |
LOx= min(LOx, xx); HIx= max(HIx, xx) /*determine the X MIN and MAX. */ |
||
Line 1,336: | Line 2,434: | ||
exit /*stick a fork in it, we're all done. */ |
exit /*stick a fork in it, we're all done. */ |
||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
pi: |
pi: pi=3.1415926535897932384626433832795028841971693993751058209749445923078; return pi |
||
plot: |
plot: do row=HIy to LOy by -1; say substr(@.row, LOx+1); end; return |
||
r2r: |
r2r: return arg(1) // (pi() * 2) /*normalize radians ───► a unit circle.*/ |
||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
|||
cos: procedure; parse arg x; x= r2r(x); a= abs(x); hpi= pi * .5 |
|||
numeric fuzz min(6, digits() - 3); if a=pi then return -1 |
|||
if a=hpi | a=hpi*3 then return 0 if a=pi / 3 then return .5 |
|||
if a=pi * 2 / 3 then return -.5; return .sinCos(1, -1) |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
cos: procedure; parse arg x; x= r2r(x); _= 1; a= abs(x); hpi= pi * .5 |
|||
numeric fuzz min(6, digits() - 3); if a=pi then return -1 |
|||
if a=hpi | a=hpi*3 then return 0 if a=pi / 3 then return .5 |
|||
if a=pi * 2 / 3 then return -.5; q= x*x; z= 1 |
|||
do k=2 by 2 until p=z; p= z; _= -_ *q/(k*k-k); z= z+_; end; return z |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
sin: procedure; parse arg x; x= r2r(x); _= x; numeric fuzz min(5, max(1, digits() -3)) |
|||
if x=pi * .5 then return 1; if x==pi*1.5 then return -1 |
|||
if abs(x)=pi | x=0 then return 0; q= x*x; z= x |
|||
do k=2 by 2 until p=z; p= z; _= -_ *q/(k*k+k); z= z+_; end; return z</syntaxhighlight> |
|||
{{out|output|text= when using the following inputs: <tt> 13 , 5 , db </tt>}} |
{{out|output|text= when using the following inputs: <tt> 13 , 5 , db </tt>}} |
||
Line 1,550: | Line 2,647: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
/* |
/* |
||
+--------------------------------------------------------------------------------------------------------- |
+--------------------------------------------------------------------------------------------------------- |
||
Line 1,655: | Line 2,752: | ||
return |
return |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|RPL}}== |
|||
[[File:Archimedean.png|thumb|right|HP-48G emulator screenshot]] |
|||
{{works with|HP|48G}} |
|||
« → a b |
|||
« -20 20 DUP2 XRNG YRNG |
|||
POLAR RAD 'a+b*t' STEQ { t 0 18.9 } INDEP |
|||
ERASE DRAW { } PVIEW |
|||
{ EQ PPAR } PURGE |
|||
» » '<span style="color:blue">ARCHI</span>' STO |
|||
1 1 <span style="color:blue">ARCHI</span> |
|||
=={{header|Ruby}}== |
|||
{{libheader|RubyGems}} |
|||
{{libheader|JRubyArt}} |
|||
JRubyArt is an implementation of Processing in ruby, that uses JRuby to provide the interoperability with the java libraries. |
|||
<syntaxhighlight lang="ruby"> |
|||
INCR = 0.1 |
|||
attr_reader :x, :theta |
|||
def setup |
|||
sketch_title 'Archimedian Spiral' |
|||
@theta = 0 |
|||
@x = 0 |
|||
background(255) |
|||
translate(width / 2.0, height / 2.0) |
|||
begin_shape |
|||
(0..50*PI).step(INCR) do |theta| |
|||
@x = theta * cos(theta / PI) |
|||
curve_vertex(x, theta * sin(theta / PI)) |
|||
end |
|||
end_shape |
|||
end |
|||
def settings |
|||
size(300, 300) |
|||
end |
|||
</syntaxhighlight> |
|||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
< |
<syntaxhighlight lang="rust">#[macro_use(px)] |
||
extern crate bmp; |
extern crate bmp; |
||
Line 1,689: | Line 2,825: | ||
// Save the image |
// Save the image |
||
let _ = img.save("archimedean_spiral.bmp").unwrap_or_else(|e| panic!("Failed to save: {}", e)); |
let _ = img.save("archimedean_spiral.bmp").unwrap_or_else(|e| panic!("Failed to save: {}", e)); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|SAS}}== |
=={{header|SAS}}== |
||
< |
<syntaxhighlight lang="sas">data xy; |
||
h=constant('pi')/40; |
h=constant('pi')/40; |
||
do i=0 to 400; |
do i=0 to 400; |
||
Line 1,705: | Line 2,841: | ||
proc sgplot; |
proc sgplot; |
||
series x=x y=y; |
series x=x y=y; |
||
run;</ |
run;</syntaxhighlight> |
||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
===Java Swing Interoperability=== |
===Java Swing Interoperability=== |
||
<syntaxhighlight lang="scala"> |
|||
<lang Scala> |
|||
object ArchimedeanSpiral extends App { |
object ArchimedeanSpiral extends App { |
||
Line 1,776: | Line 2,912: | ||
) |
) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Scilab}}== |
|||
<lang>a = 3; |
|||
b = 2; |
|||
theta = linspace(0,10*%pi,1000); |
|||
r = a + b .* theta; |
|||
//1. Plot using polar coordinates |
|||
scf(1); |
|||
polarplot(theta,r); |
|||
//2. Plot using rectangular coordinates |
|||
//2.1 Convert coordinates using Euler's formula |
|||
z = r .* exp(%i .* theta); |
|||
x = real(z); |
|||
y = imag(z); |
|||
scf(2); |
|||
plot2d(x,y);</lang> |
|||
=={{header|Scheme}}== |
=={{header|Scheme}}== |
||
{{libheader|Scheme/PsTk}} |
{{libheader|Scheme/PsTk}} |
||
< |
<syntaxhighlight lang="scheme"> |
||
(import (scheme base) |
(import (scheme base) |
||
(scheme complex) |
(scheme complex) |
||
Line 1,835: | Line 2,952: | ||
(draw-spiral canvas)) |
(draw-spiral canvas)) |
||
(tk-event-loop tk)) |
(tk-event-loop tk)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Scilab}}== |
|||
<syntaxhighlight lang="text">a = 3; |
|||
b = 2; |
|||
theta = linspace(0,10*%pi,1000); |
|||
r = a + b .* theta; |
|||
//1. Plot using polar coordinates |
|||
scf(1); |
|||
polarplot(theta,r); |
|||
//2. Plot using rectangular coordinates |
|||
//2.1 Convert coordinates using Euler's formula |
|||
z = r .* exp(%i .* theta); |
|||
x = real(z); |
|||
y = imag(z); |
|||
scf(2); |
|||
plot2d(x,y);</syntaxhighlight> |
|||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||
< |
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i"; |
||
include "draw.s7i"; |
include "draw.s7i"; |
||
include "keybd.s7i"; |
include "keybd.s7i"; |
||
Line 1,863: | Line 3,000: | ||
theta +:= delta; |
theta +:= delta; |
||
end while; |
end while; |
||
flushGraphic; |
|||
ignore(getc(KEYBOARD)); |
ignore(getc(KEYBOARD)); |
||
end func;</ |
end func;</syntaxhighlight> |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
{{trans| |
{{trans|Raku}} |
||
< |
<syntaxhighlight lang="ruby">require('Imager') |
||
define π = Num.pi |
define π = Num.pi |
||
Line 1,883: | Line 3,020: | ||
} |
} |
||
img.write(file => 'Archimedean_spiral.png')</ |
img.write(file => 'Archimedean_spiral.png')</syntaxhighlight> |
||
Output image: [https://github.com/trizen/rc/blob/master/img/archimedean-spiral-sidef.png Archimedean spiral] |
Output image: [https://github.com/trizen/rc/blob/master/img/archimedean-spiral-sidef.png Archimedean spiral] |
||
=={{header|Stata}}== |
=={{header|Stata}}== |
||
< |
<syntaxhighlight lang="stata">clear all |
||
scalar h=_pi/40 |
scalar h=_pi/40 |
||
set obs 400 |
set obs 400 |
||
Line 1,893: | Line 3,030: | ||
gen x=(1+t)*cos(t) |
gen x=(1+t)*cos(t) |
||
gen y=(1+t)*sin(t) |
gen y=(1+t)*sin(t) |
||
line y x</ |
line y x</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
This creates a little Tk GUI where you can interactively enter values for `a` and `b`. The spiral will be re-drawn automatically thanks to `trace`: |
This creates a little Tk GUI where you can interactively enter values for `a` and `b`. The spiral will be re-drawn automatically thanks to `trace`: |
||
< |
<syntaxhighlight lang="tcl">package require Tk |
||
# create widgets |
# create widgets |
||
Line 1,962: | Line 3,099: | ||
update ;# lay out widgets before trying to draw |
update ;# lay out widgets before trying to draw |
||
draw |
draw |
||
vwait forever ;# go into event loop until window is closed</ |
vwait forever ;# go into event loop until window is closed</syntaxhighlight> |
||
=={{header| |
=={{header|Wren}}== |
||
{{trans|Sidef}} |
|||
<lang vb>Private Sub plot_coordinate_pairs(x As Variant, y As Variant) |
|||
{{libheader|DOME}} |
|||
Dim chrt As Chart |
|||
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color |
|||
Set chrt = ActiveSheet.Shapes.AddChart.Chart |
|||
import "dome" for Window |
|||
With chrt |
|||
.ChartType = xlXYScatter |
|||
class Game { |
|||
.HasLegend = False |
|||
static init() { |
|||
.SeriesCollection.NewSeries |
|||
Window.title = "Archimedean Spiral" |
|||
.SeriesCollection.Item(1).XValues = x |
|||
__width = 400 |
|||
__height = 400 |
|||
End With |
|||
Canvas.resize(__width, __height) |
|||
End Sub |
|||
Window.resize(__width, __height) |
|||
Public Sub main() |
|||
var col = Color.red |
|||
Dim x(1000) As Single, y(1000) As Single |
|||
spiral(col) |
|||
} |
|||
For i = 0 To 1000 |
|||
static spiral(col) { |
|||
theta = i * WorksheetFunction.Pi() / 60 |
|||
var theta = 0 |
|||
while (theta < 52 * Num.pi) { |
|||
var x = ((theta/Num.pi).cos * theta + __width/2).truncate |
|||
var y = ((theta/Num.pi).sin * theta + __height/2).truncate |
|||
Next i |
|||
Canvas.pset(x, y, col) |
|||
plot_coordinate_pairs x, y |
|||
theta = theta + 0.025 |
|||
End Sub</lang> |
|||
} |
|||
=={{header|Yabasic}}== |
|||
} |
|||
{{trans|Sinclair_ZX81_BASIC}} |
|||
<lang Yabasic>5 OPEN WINDOW 320, 200 : WINDOW ORIGIN "CC" |
|||
static update() {} |
|||
10 LET A=1.5 |
|||
20 LET B=0.7 |
|||
static draw(dt) {} |
|||
30 FOR T=0 TO 30*PI STEP 0.05 |
|||
}</syntaxhighlight> |
|||
40 LET R=A+B*T |
|||
50 LINE TO R*COS(T),R*SIN(T) |
|||
{{out}} |
|||
60 NEXT T</lang> |
|||
[[File:Wren-Archimedean_spiral.png]] |
|||
=={{header|XPL0}}== |
|||
Looks a lot like the C++ image. |
|||
<syntaxhighlight lang="xpl0">real A, B, R, T, X, Y; |
|||
[SetVid($12); \set 640x480 graphics |
|||
A:= 0.0; B:= 3.0; T:= 0.0; |
|||
Move(320, 240); \start at center of screen |
|||
repeat R:= A + B*T; |
|||
X:= R*Cos(T); Y:= R*Sin(T); |
|||
Line(fix(X)+320, 240-fix(Y), 4\red\); |
|||
T:= T + 0.03; \increase angle (Theta) |
|||
until T >= 314.159; \50 revs |
|||
]</syntaxhighlight> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
[[File:ArchimedeanSpiral.zk.jpg|250px|thumb|right]] |
[[File:ArchimedeanSpiral.zk.jpg|250px|thumb|right]] |
||
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl |
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl |
||
< |
<syntaxhighlight lang="zkl">fcn archimedeanSpiral(a,b,circles){ |
||
w,h:=640,640; centerX,centerY:=w/2,h/2; |
w,h:=640,640; centerX,centerY:=w/2,h/2; |
||
bitmap:=PPM(w+1,h+1,0xFF|FF|FF); // White background |
bitmap:=PPM(w+1,h+1,0xFF|FF|FF); // White background |
||
Line 2,012: | Line 3,163: | ||
} |
} |
||
bitmap.writeJPGFile("archimedeanSpiral.jpg"); |
bitmap.writeJPGFile("archimedeanSpiral.jpg"); |
||
}(0,5,7);</ |
}(0,5,7);</syntaxhighlight> |
Latest revision as of 12:43, 14 July 2024
You are encouraged to solve this task according to the task description, using any language you may know.
The Archimedean spiral is a spiral named after the Greek mathematician Archimedes.
An Archimedean spiral can be described by the equation:
with real numbers a and b.
- Task
Draw an Archimedean spiral.
Action!
Action! does not provide trigonometric functions. Therefore a simple implementation for Sin and Cos function has been provided.
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 DrawSpiral(INT x0,y0)
INT angle,radius,x,y
Plot(x0,y0)
FOR angle=0 TO 1800 STEP 5
DO
radius=angle/20
x=radius*Cos(angle)/256+x0
y=radius*Sin(angle)/256+y0
DrawTo(x,y)
OD
RETURN
PROC Main()
BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6
Graphics(8+16)
Color=1
COLOR1=$0C
COLOR2=$02
DrawSpiral(160,96)
DO UNTIL CH#$FF OD
CH=$FF
RETURN
- Output:
Screenshot from Atari 8-bit computer
Ada
with Ada.Numerics.Elementary_Functions;
with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Events.Events;
procedure Archimedean_Spiral is
Width : constant := 800;
Height : constant := 800;
A : constant := 4.2;
B : constant := 3.2;
T_First : constant := 4.0;
T_Last : constant := 100.0;
Window : SDL.Video.Windows.Window;
Renderer : SDL.Video.Renderers.Renderer;
Event : SDL.Events.Events.Events;
procedure Draw_Archimedean_Spiral is
use type SDL.C.int;
use Ada.Numerics.Elementary_Functions;
Pi : constant := Ada.Numerics.Pi;
Step : constant := 0.002;
T : Float;
R : Float;
begin
T := T_First;
loop
R := A + B * T;
Renderer.Draw
(Point => (X => Width / 2 + SDL.C.int (R * Cos (T, 2.0 * Pi)),
Y => Height / 2 - SDL.C.int (R * Sin (T, 2.0 * Pi))));
exit when T >= T_Last;
T := T + Step;
end loop;
end Draw_Archimedean_Spiral;
procedure Wait is
use type SDL.Events.Event_Types;
begin
loop
while SDL.Events.Events.Poll (Event) loop
if Event.Common.Event_Type = SDL.Events.Quit then
return;
end if;
end loop;
end loop;
end Wait;
begin
if not SDL.Initialise (Flags => SDL.Enable_Screen) then
return;
end if;
SDL.Video.Windows.Makers.Create (Win => Window,
Title => "Archimedean spiral",
Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
Size => SDL.Positive_Sizes'(Width, Height),
Flags => 0);
SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
Renderer.Set_Draw_Colour ((0, 0, 0, 255));
Renderer.Fill (Rectangle => (0, 0, Width, Height));
Renderer.Set_Draw_Colour ((0, 220, 0, 255));
Draw_Archimedean_Spiral;
Window.Update_Surface;
Wait;
Window.Finalize;
SDL.Finalise;
end Archimedean_Spiral;
ALGOL 68
ASCII art.
BEGIN # draw an Archimedian spiral using ASCII art #
# Translation of Applesoft Basic via AWK and Algol W #
PROC max = ( INT x, y )INT: IF x > y THEN x ELSE y FI;
PROC min = ( INT x, y )INT: IF x < y THEN x ELSE y FI;
[ 1 : 255, 1 : 255 ]CHAR arr;
FOR i FROM 1 LWB arr TO 1 UPB arr DO
FOR j FROM 2 LWB arr TO 2 UPB arr DO arr[ i, j ] := " " OD
OD;
INT x min := 1 UPB arr + 1, y min := 2 UPB arr + 1;
INT x max := 1 LWB arr - 1, y max := 2 LWB arr - 1;
REAL m = 6 * pi, h = 96, s = 0.02;
REAL w = 1.5 * h;
REAL t := s;
WHILE t <= m DO # build spiral #
REAL r = t + 1;
INT x = ROUND ( r * cos( t ) + w );
INT y = ROUND ( r * sin( t ) + h );
IF x >= 1 LWB arr AND y >= 2 LWB arr
AND x <= 1 UPB arr AND y <= 2 UPB arr
THEN
arr[ x, y ] := "*";
x min := min( x min, x );
x max := max( x max, x );
y min := min( y min, y );
y max := max( y max, y );
FI;
t +:= s
OD;
FOR i FROM x min TO x max DO # print spiral #
FOR j FROM y min TO y max DO
CHAR c = arr[ i, j ];
print( ( c, c ) )
OD;
print( ( newline ) )
OD
END
- Output:
************** ******** ******** ****** **** **** ****** **** **** **** **** **** **** **** ****************** ** **** **** ****** ** ** **** **** **** **** ** **** ** ** **** **** ** ** **** ** ** ** ** ********** **** ** ** **** **** **** ** ** ** ** ** **** ** ** ** ** **** ** ** ** ** ** ** **** ** ** ** ** ** ****** ** ** ** ** ** **** ** ** ** **** ** ** ** ** ** **** ** ** ** **** **** ** ** ** ****** **** **** ** **** ************** ** ** ** ** **** ** **** ** **** **** **** **** ****** ** ****** ****** ** ******** ******** ** ********** ** **** ****** ****** ******** ********
ALGOL W
This version doubles the characters horiontally to give a slightly more rounded shape.
begin % draw an Archimedian spiral %
% Translation of AWK which was a trnslation of Applesoft Basic program %
integer procedure max ( integer x, y ) ; begin if x > y then x else y end;
integer procedure min ( integer x, y ) ; begin if x < y then x else y end;
integer x_min, y_min, x_max, y_max, x, y;
string(255) array arr ( 1 :: 255 );
real h, w, m, s, t;
for i := 1 until 255 do arr( i ) := " ";
x_min := y_min := 9999;
x_max := y_max := 0;
h := 96;
w := h + h / 2;
m := 6 * PI;
s := 0.02;
t := s;
while t <= m do begin % build spiral %
real r;
r := t + 1;
x := round(r * cos(t) + w);
y := round(r * sin(t) + h);
if x > 0 and y > 0 and x < 256 and y < 256 then begin
arr( x )( y // 1 ) := "*";
x_min := min(x_min,x);
x_max := max(x_max,x);
y_min := min(y_min,y);
y_max := max(y_max,y)
end if_x_and_y_in_range ;
t := t + s
end while__t_le_m ;
for i := x_min until x_max do begin % print spiral %
for j := y_min until y_max do begin
string(1) c;
c := arr( i )( j // 1 );
writeon( c, c )
end for_j ;
write()
end for_i
end.
- Output:
************** ******** ******** ****** **** **** ****** **** **** **** **** **** **** **** ****************** ** **** **** ****** ** ** **** **** **** **** ** **** ** ** **** **** ** ** **** ** ** ** ** ********** **** ** ** **** **** **** ** ** ** ** ** **** ** ** ** ** **** ** ** ** ** ** ** **** ** ** ** ** ** ****** ** ** ** ** ** **** ** ** ** **** ** ** ** ** ** **** ** ** ** **** **** ** ** ** ****** **** **** ** **** ************** ** ** ** ** **** ** **** ** **** **** **** **** ****** ** ****** ****** ** ******** ******** ** ********** ** **** ****** ****** ******** ********
Amazing Hopper
#include <jambo.h>
Main
Set break
a=1.5, b=1.5, r=0, origen x=200, origen y=105
total = 0, Let ( total := Mul(20, M_PI) )
Cls
Loop for ( t=0, var 't' Is less equal to 'total', Let (t := Add (t, 0.005)) )
#( r = a + b * t )
Set 'origen x, origen y', # ( 200 + (2*r*sin(t)) ) » 'origen x', #( 105 + (r*cos(t)) ) » 'origen y',
Gosub 'Dibuja un segmento'
Next
Pause
End
Subrutines
Define (Dibuja un segmento, x1, y1, x2, y2)
dx=0, dy=0, paso=0, i=0, DX=0, DY=0
Sub(x2, x1), Sub (y2, y1), Move to ' dx, dy '
Let( paso := Get if( Greater equal ( Abs(dx) » (DX), Abs(dy)»(DY) ), DX, DY ) )
// incremento:
Div(dx, paso), Div(dy, paso), Move to ( dx, dy )
Color back (13)
// dibuja línea:
i = 0
Loop if ( Less equal (i, paso) )
Locate( y1, x1 ), Printnl( " " )
Add ( x1, dx), Add( y1, dy ), Move to ( x1, y1 )
++i
Back
Printnl("\OFF")
Return
- Output:
Invocar como: rxvt -g 500x250 -fn "xft:FantasqueSansMono-Regular:pixelsize=1" -e hopper jm/archi.jambo
APL
Works in: Dyalog APL
Uses Dyalog's SharpPlot integration, which works on all supported platforms.
'InitCauseway' 'View' ⎕CY 'sharpplot'
InitCauseway ⍬ ⍝ initialise current namespace
sp←⎕NEW Causeway.SharpPlot
sp.DrawPolarChart {⍵(360|⍵)}⌽⍳720
View sp
AutoHotkey
Requires GDIP
if !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
OnExit, Exit
SysGet, MonitorPrimary, MonitorPrimary
SysGet, WA, MonitorWorkArea, %MonitorPrimary%
WAWidth := WARight-WALeft
WAHeight := WABottom-WATop
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA
hwnd1 := WinExist()
hbm := CreateDIBSection(WAWidth, WAHeight)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetSmoothingMode(G, 4)
pPen := Gdip_CreatePen(0xffff0000, 3)
;--------------------------------
a := 1, b := 4, th := 0.1, step := 0.1
loop, 720
{
th += step
r := a + b * th
x1 := r * Cos(th)
y1 := r * Sin(th)
x1 += A_ScreenWidth/2
y1 += A_ScreenHeight/2
if (x2 && y2)
Gdip_DrawLine(G, pPen, x1, y1, x2, y2)
x2 := x1, y2 := y1
if GetKeyState("Esc", "P")
break
; next two lines are optional to watch it draw
; Sleep 10
; UpdateLayeredWindow(hwnd1, hdc, WALeft, WATop, WAWidth, WAHeight)
}
UpdateLayeredWindow(hwnd1, hdc, WALeft, WATop, WAWidth, WAHeight)
;--------------------------------
return
Exit:
Gdip_DeletePen(pPen)
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
ExitApp
Return
AWK
# syntax: GAWK -f ARCHIMEDEAN_SPIRAL.AWK
# converted from Applesoft BASIC
BEGIN {
x_min = y_min = 9999
x_max = y_max = 0
h = 96
w = h + h / 2
a = 1
b = 1
m = 6 * 3.1415926
step = .02
for (t=step; t<=m; t+=step) { # build spiral
r = a + b * t
x = int(r * cos(t) + w)
y = int(r * sin(t) + h)
if (x <= 0 || y <= 0) { continue }
if (x >= 280 ) { continue }
if (y >= 192) { continue }
arr[x,y] = "*"
x_min = min(x_min,x)
x_max = max(x_max,x)
y_min = min(y_min,y)
y_max = max(y_max,y)
}
for (i=x_min; i<=x_max; i++) { # print spiral
rec = ""
for (j=y_min; j<=y_max; j++) {
rec = sprintf("%s%1s",rec,arr[i,j])
}
printf("%s\n",rec)
}
exit(0)
}
function max(x,y) { return((x > y) ? x : y) }
function min(x,y) { return((x < y) ? x : y) }
- Output:
********** *** *** ** ** ** ** ** ** ** ** ** ******* ** ** *** *** * * ** ** ** ** ** ** * * ** ** ** ** ** * * * * **** * * * * *** ** * ** ** * * ** * * * * ** * * * * * * * * * * ** * ** * * * ** * ** * ** * * * ** * * * * * * ** * * ** ** * * ** ** * * * *** *** ** ** ** ****** * * * ** * ** ** * ** ** ** ** ** * **** *** * ******** * * ** *** **** *****
BASIC
AmigaBASIC
a=1.5
b=1.5
pi=3.141592
PSET (320,100)
FOR t=0 TO 40*pi STEP .1
r=a+b*t
LINE -(320+2*r*SIN(t),100+r*COS(t))
NEXT
Applesoft BASIC
110 LET H = 96
120 LET W = H + H / 2
130 HGR2
140 HCOLOR= 3
150 LET A = 1
160 LET B = 9
170 LET PI = 3.1415926535
180 LET M = 10 * PI
190 LET S = .02
200 FOR T = S TO M STEP S
210 LET R = A + B * T
220 LET X = R * COS (T) + W
230 LET Y = R * SIN (T) + H
240 IF X < 0 THEN 290
250 IF Y < 0 THEN 290
260 IF X > 279 THEN 290
270 IF Y > 191 THEN 290
280 HPLOT X,Y
290 NEXT
BASIC256
# Basic-256 ver 1.1.4
# Archimedean Spiral
width = 430 : height = 430
graphsize width, height
rect 0,0, graphwidth,graphheight
penwidth 1
color green
x = width/2 : y = height/2 # Center of graphics window
i = 1 : t = 0 : xn = 0 : yn = 0 # Initial values
iter = 150 : q = 30
line x,0,x,height
line 0,y,width,y
penwidth 2
color red
while i <= iter
t = i / q * pi
xn = (1 + (1 * t)) * cos(t) +x
yn = (1 + (1 * t)) * sin(t) +y
line x,y,xn,yn
x = xn : y = yn
print i + chr(9) + int(x) + chr(9) + int(y) + chr(9) + int(t) # chr(9) = TAB
i += 1
end while
imgsave "spiral-Basic-256.png", "PNG"
BBC BASIC
A=320
VDU 23, 22, A+10; A+10; 8, 16, 16, 128
ORIGIN @size.x%, @size.y%
GCOL 7
FOR I=-(A - A MOD 100) TO A - A MOD 100 STEP 100
LINE I, -A, I, A : LINE -A, I, A, I
NEXT
MOVE 0, 0
GCOL 1
VDU 23, 23, 3|
FOR I=0 TO 5 * PI STEP .05
R=A / 16 * I
DRAW R * COS(I), R * SIN(I)
NEXT
Chipmunk Basic
10 rem Archimedean spiral
20 graphics 0
30 graphics cls
40 a = 3 : b = 1.4
50 x0 = 320 : y0 = 200
60 graphics moveto x0,y0
70 for t = 0 to 40*pi step 0.2
80 r = a+b*t
90 x = r*cos(t)+320 : y = r*sin(t)+200
100 graphics lineto x,y
110 next t
120 end
Commodore BASIC
Commodore BASIC 2.0 lacks in-built graphics capability. This implementation is written for Commodore BASIC 7.0 that was built into the Commodore 128 computer. Should also work for Commodore BASIC 3.5.
1 REM ARCHIMEDEAN SPIRAL
2 REM USING COMMODORE BASIC 7.0
3 REM OF THE COMMODORE 128
4 REM **********************************
10 GRAPHIC 1,1
20 A = 1.5
30 B = 0.7
40 X0 = 160 : Y0 = 100
50 FOR T = 0 TO 40*π STEP 0.2
60 R = A+B*T
70 X = R*COS(T)+160 : Y = R*SIN(T)+100
80 DRAW 1,X0,Y0 TO X,Y
90 X0 = X : Y0 = Y
100 NEXT T
110 GOTO 110
FreeBASIC
' version 16-10-2016
' compile with: fbc -s gui
Const As double deg2rad = Atn(1) * 4 / 180 ' pi = atn(1) * 4, pi/180
Const As UInteger screensize = 600 ' size of window in pixels
Const As Double turns = 5 ' number of turns
Const As UInteger halfscrn = screensize \ 2
Const As uinteger sf = (turns * (screensize - 100)) / halfscrn
ScreenRes screensize, screensize, 32 ' screen 600 * 600 pixels, 4 byte color
Dim As Double r, x, y
For r = 0 To turns * 360 Step 0.05
x = Cos(r * deg2rad) * r / sf
y = Sin(r * deg2rad) * r / sf
PSet(halfscrn + x, halfscrn - y), RGB(255, 255, 255)
Next
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End
GW-BASIC
10 A = 0
20 B = 1
30 SCREEN 1
40 FOR THETA = 0 TO 160 STEP .01
50 R = A + B*THETA
60 X = R*COS(THETA)
70 Y = R*SIN(THETA)
80 PSET (160+X, 100-Y),3
90 NEXT THETA
100 IF INKEY$="" THEN GOTO 100
110 SCREEN 2:SCREEN 0
120 END
IS-BASIC
100 GRAPHICS LORES 2
110 OPTION ANGLE DEGREES
120 PLOT 640,360,ANGLE 90;
130 FOR I=2 TO 33.2 STEP .05
140 PLOT FORWARD I,LEFT 5;
150 NEXT
Locomotive Basic
10 a=1.5:b=2
20 mode 2:rad:move 320,200
30 for t=0 to 40*pi step 0.2
40 r=a+b*t
50 draw r*sin(t)+320,r*cos(t)+200
60 next
70 while inkey$="":wend
PureBasic
#MAXLOOP = 7*360
#XCENTER = 640/2
#YCENTER = 480/2
#SCALAR = 200
If OpenWindow(0, 100, 200, 640, 480, "Archimedean spiral")
If CreateImage(0, 640, 480,24,RGB(255,255,255))
If StartDrawing(ImageOutput(0))
i.f=0.0
While i<=#MAXLOOP
x.f=#XCENTER+Cos(Radian(i))*#SCALAR*i/#MAXLOOP
y.f=#YCENTER+Sin(Radian(i))*#SCALAR*i/#MAXLOOP
Plot(x,y,RGB(50,50,50))
i+0.05
Wend
StopDrawing()
EndIf
EndIf
ImageGadget(0, 0, 0, 0, 0, ImageID(0))
Repeat : Event = WaitWindowEvent() : Until Event = #PB_Event_CloseWindow
EndIf
End
Run BASIC
'archimedean spiral.bas
'runs in Run Basic
'Run Basic website http://www.runbasic.com
'From Rosettacode.org/wiki/ *** Liberty_BASIC
graphic #g, 300,300 'width and height - the center is 150
c = 255 '255 for white '0 for black
print "Welcome to the Arch-Spiral Program"
pi=acs(-1)
nLoops = 5
#g cls("blue") 'blue background color
#g color(c,c,c) 'set line color - see color above
for t=0 to 2*pi*nLoops step 0.01
'c = c - 1 'changes color parameter
x=100*t/(2*pi*nLoops)*cos(t)+150 '150x150 is the center
y=100*t/(2*pi*nLoops)*sin(t)+150
#g color(c,c,c) 'changes color
#g set(x,y)
'if c <1 then c=255
next
render #g
print "Thank you and Goodbye"
end
End
QBasic
SCREEN 12
WINDOW (-2.67, -2!)-(2.67, 2!)
PI = 4 * ATN(1)
H = PI / 40
A = .2: B = .05
PSET (A, 0)
FOR I = 0 TO 400
T = I * H
X = (A + B * T) * COS(T)
Y = (A + B * T) * SIN(T)
LINE -(X, Y)
NEXT
Sinclair ZX81 BASIC
Works with the unexpanded (1k RAM) ZX81. The output is quite blocky, but identifiably a spiral.
10 LET A=1.5
20 LET B=0.7
30 FOR T=0 TO 7*PI STEP 0.05
40 LET R=A+B*T
50 PLOT R*COS T+32,R*SIN T+22
60 NEXT T
- Output:
Screenshot here.
VBA
Private Sub plot_coordinate_pairs(x As Variant, y As Variant)
Dim chrt As Chart
Set chrt = ActiveSheet.Shapes.AddChart.Chart
With chrt
.ChartType = xlXYScatter
.HasLegend = False
.SeriesCollection.NewSeries
.SeriesCollection.Item(1).XValues = x
.SeriesCollection.Item(1).Values = y
End With
End Sub
Public Sub main()
Dim x(1000) As Single, y(1000) As Single
a = 1
b = 9
For i = 0 To 1000
theta = i * WorksheetFunction.Pi() / 60
r = a + b * theta
x(i) = r * Cos(theta)
y(i) = r * Sin(theta)
Next i
plot_coordinate_pairs x, y
End Sub
Yabasic
5 OPEN WINDOW 320, 200 : WINDOW ORIGIN "CC"
10 LET A=1.5
20 LET B=0.7
30 FOR T=0 TO 30*PI STEP 0.05
40 LET R=A+B*T
50 LINE TO R*COS(T),R*SIN(T)
60 NEXT T
BQN
The BQN online REPL supports some basic plotting functionality through •Plot
. This is used to create a spiral plotting function:
{(•math.Sin •Plot○(⊢×↕∘≠) •math.Cos) -(2×π) × 𝕩⥊(↕÷-⟜1)100}
When called with argument 200, it is similar to the given example diagram.
C
Interactive code which asks the parameters a and b as inputs, the number of cycles and the division steps. Requires the WinBGIm library.
#include<graphics.h>
#include<stdio.h>
#include<math.h>
#define pi M_PI
int main(){
double a,b,cycles,incr,i;
int steps,x=500,y=500;
printf("Enter the parameters a and b : ");
scanf("%lf%lf",&a,&b);
printf("Enter cycles : ");
scanf("%lf",&cycles);
printf("Enter divisional steps : ");
scanf("%d",&steps);
incr = 1.0/steps;
initwindow(1000,1000,"Archimedean Spiral");
for(i=0;i<=cycles*pi;i+=incr){
putpixel(x + (a + b*i)*cos(i),x + (a + b*i)*sin(i),15);
}
getch();
closegraph();
}
C#
using System;
using System.Linq;
using System.Drawing;
using System.Diagnostics;
using System.Drawing.Drawing2D;
class Program
{
const int width = 380;
const int height = 380;
static PointF archimedeanPoint(int degrees)
{
const double a = 1;
const double b = 9;
double t = degrees * Math.PI / 180;
double r = a + b * t;
return new PointF { X = (float)(width / 2 + r * Math.Cos(t)), Y = (float)(height / 2 + r * Math.Sin(t)) };
}
static void Main(string[] args)
{
var bm = new Bitmap(width, height);
var g = Graphics.FromImage(bm);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.FillRectangle(new SolidBrush(Color.White), new Rectangle { X = 0, Y = 0, Width = width, Height = height });
var pen = new Pen(Color.OrangeRed, 1.5f);
var spiral = Enumerable.Range(0, 360 * 3).AsParallel().AsOrdered().Select(archimedeanPoint);
var p0 = new PointF(width / 2, height / 2);
foreach (var p1 in spiral)
{
g.DrawLine(pen, p0, p1);
p0 = p1;
}
g.Save(); // is this really necessary ?
bm.Save("archimedes-csharp.png");
Process.Start("archimedes-csharp.png"); // Launches default photo viewing app
}
}
C++
#include <windows.h>
#include <string>
#include <iostream>
const int BMP_SIZE = 600;
class myBitmap {
public:
myBitmap() : pen( NULL ), brush( NULL ), clr( 0 ), wid( 1 ) {}
~myBitmap() {
DeleteObject( pen ); DeleteObject( brush );
DeleteDC( hdc ); DeleteObject( bmp );
}
bool create( int w, int h ) {
BITMAPINFO bi;
ZeroMemory( &bi, sizeof( bi ) );
bi.bmiHeader.biSize = sizeof( bi.bmiHeader );
bi.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biWidth = w;
bi.bmiHeader.biHeight = -h;
HDC dc = GetDC( GetConsoleWindow() );
bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
if( !bmp ) return false;
hdc = CreateCompatibleDC( dc );
SelectObject( hdc, bmp );
ReleaseDC( GetConsoleWindow(), dc );
width = w; height = h;
return true;
}
void clear( BYTE clr = 0 ) {
memset( pBits, clr, width * height * sizeof( DWORD ) );
}
void setBrushColor( DWORD bClr ) {
if( brush ) DeleteObject( brush );
brush = CreateSolidBrush( bClr );
SelectObject( hdc, brush );
}
void setPenColor( DWORD c ) {
clr = c; createPen();
}
void setPenWidth( int w ) {
wid = w; createPen();
}
void saveBitmap( std::string path ) {
BITMAPFILEHEADER fileheader;
BITMAPINFO infoheader;
BITMAP bitmap;
DWORD wb;
GetObject( bmp, sizeof( bitmap ), &bitmap );
DWORD* dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
infoheader.bmiHeader.biCompression = BI_RGB;
infoheader.bmiHeader.biPlanes = 1;
infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
infoheader.bmiHeader.biHeight = bitmap.bmHeight;
infoheader.bmiHeader.biWidth = bitmap.bmWidth;
infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
fileheader.bfType = 0x4D42;
fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
fileheader.bfSize = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
HANDLE file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL );
WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
CloseHandle( file );
delete [] dwpBits;
}
HDC getDC() const { return hdc; }
int getWidth() const { return width; }
int getHeight() const { return height; }
private:
void createPen() {
if( pen ) DeleteObject( pen );
pen = CreatePen( PS_SOLID, wid, clr );
SelectObject( hdc, pen );
}
HBITMAP bmp; HDC hdc;
HPEN pen; HBRUSH brush;
void *pBits; int width, height, wid;
DWORD clr;
};
class spiral {
public:
spiral() {
bmp.create( BMP_SIZE, BMP_SIZE );
}
void draw( int c, int s ) {
double a = .2, b = .3, r, x, y;
int w = BMP_SIZE >> 1;
HDC dc = bmp.getDC();
for( double d = 0; d < c * 6.28318530718; d += .002 ) {
r = a + b * d; x = r * cos( d ); y = r * sin( d );
SetPixel( dc, ( int )( s * x + w ), ( int )( s * y + w ), 255 );
}
// saves the bitmap
bmp.saveBitmap( "./spiral.bmp" );
}
private:
myBitmap bmp;
};
int main(int argc, char* argv[]) {
spiral s; s.draw( 16, 8 ); return 0;
}
Clojure
(use '(incanter core stats charts io))
(defn Arquimidean-function
[a b theta]
(+ a (* theta b)))
(defn transform-pl-xy [r theta]
(let [x (* r (sin theta))
y (* r (cos theta))]
[x y]))
(defn arq-spiral [t] (transform-pl-xy (Arquimidean-function 0 7 t) t))
(view (parametric-plot arq-spiral 0 (* 10 Math/PI)))
Another version inspired by the Java below, showing how to interop with awt/swing to do simple graphics:
(let [panel (proxy [javax.swing.JPanel] []
(paintComponent [g]
(proxy-super paintComponent g)
(.setStroke g (java.awt.BasicStroke. 2))
(.setRenderingHint g java.awt.RenderingHints/KEY_ANTIALIASING
java.awt.RenderingHints/VALUE_ANTIALIAS_ON)
(let [[a b] [0 (/ 1 Math/PI)]
[w h] [(.getWidth this) (.getHeight this)]
[cx cy] [(/ w 2.0) (/ h 2.0)]
margin 16
[rotations point-n] [3 (quot (min w h) 2)]
[ring-n line-n] [6 12]
scale (/ (- (min w h) (* 2 margin)) (* 2.0 ring-n))]
;; Grid
(.setColor g (java.awt.Color. 0xEEEEEE))
(doseq [i (range 1 (inc ring-n))]
(let [[posx posy] [(- cx (* i scale)) (- cy (* i scale))]]
(.drawOval g posx posy (* 2 i scale) (* 2 i scale))))
(dotimes [i line-n]
(let [theta (* 2 Math/PI (/ i (double line-n)))
[x y] [(+ cx (* scale ring-n (Math/cos theta)))
(+ cy (* scale ring-n (Math/sin theta)))]]
(.drawLine g cx cy x y)))
;; Spiral
(.setColor g (java.awt.Color. 0x202020))
(loop [i 0 [x y] [(+ cx (* a scale)) cy]]
(let [p (/ (inc i) (double point-n))
theta (* rotations 2 Math/PI p)
r (* scale (+ a (* b theta)))
[x1 y1] [(+ cx (* r (Math/cos theta)))
(- cy (* r (Math/sin theta)))]]
(.drawLine g x y x1 y1)
(when (< i (dec point-n)) (recur (inc i) [x1 y1])))))))]
(doto (javax.swing.JFrame.)
(.add (doto panel
(.setPreferredSize (java.awt.Dimension. 640 640))
(.setBackground java.awt.Color/white))
java.awt.BorderLayout/CENTER)
(.pack)
(.setVisible true)))
Common Lisp
Common Lisp doesn't provide native graphical output. Libraries or bitmapped output could be used instead, but for this solution, the output is accomplished with character printing.
(defun draw-coords-as-text (coords size fill-char)
(let* ((min-x (apply #'min (mapcar #'car coords)))
(min-y (apply #'min (mapcar #'cdr coords)))
(max-x (apply #'max (mapcar #'car coords)))
(max-y (apply #'max (mapcar #'cdr coords)))
(real-size (max (+ (abs min-x) (abs max-x)) ; bounding square
(+ (abs min-y) (abs max-y))))
(scale-factor (* (1- size) (/ 1 real-size)))
(center-x (* scale-factor -1 min-x))
(center-y (* scale-factor -1 min-y))
(intermediate-result (make-array (list size size)
:element-type 'char
:initial-element #\space)))
(dolist (c coords)
(let ((final-x (floor (+ center-x (* scale-factor (car c)))))
(final-y (floor (+ center-y (* scale-factor (cdr c))))))
(setf (aref intermediate-result final-x final-y)
fill-char)))
; print results to output
(loop for i below (array-total-size intermediate-result) do
(when (zerop (mod i size))
(terpri))
(princ (row-major-aref intermediate-result i)))))
(defun spiral (a b step-resolution step-count)
"Returns a list of coordinates for r=a+b*theta stepping theta by step-resolution"
(loop for theta
from 0 upto (* step-count step-resolution)
by step-resolution
for r = (+ a (* b theta))
for x = (* r (cos theta))
for y = (* r (sin theta))
collect (cons x y)))
(draw-coords-as-text (spiral 10 10 0.01 1500) 30 #\*)
; Output:
;
; *
; ****** *
; **** *** **
; *** ** *
; ** ** *
; ** ** *
; * ** **
; ** * *
; ** ****** * *
; * ** ** ** *
; * ** * * *
; * ** * * **
; * * * * *
; * * * ** * *
; * * *** ** *
; * ** * *
; * * ** *
; * ** ** **
; ** ** ** *
; * ** ** **
; ** ******** *
; * **
; ** **
; ** **
; ** ***
; ** **
; **** ***
; *******
;
Craft Basic
bgcolor 0, 0, 0
cls graphics
fgcolor 255, 255, 0
define pi = 3.14, size = 80
define x = 250, y = 200
define a = 1.5, b = .7
for t = 0 to size * pi step .1
let r = a + b * t
dot r * cos(t) + x, r * sin(t) + y
wait
next t
Delphi
procedure ArcSpiral(Image: TImage);
var Radius,Theta: double;
var X,Y: integer;
var Center: TPoint;
const Step = 0.2;
const Offset = 3; Spacing = 1.4;
begin
Image.Canvas.Brush.Color:=clWhite;
Image.Canvas.Rectangle(0,0,Image.Width,Image.Height);
Center:=Point(Image.Width div 2, Image.Height div 2);
Image.Canvas.MoveTo(Center.X,Center.Y);
Theta:=0;
while Theta<(40*Pi) do
begin
{Radius increases as theta increases}
Radius:=Offset+Spacing*Theta;
{Calculate position on circle}
X:=Trunc(Radius*Cos(Theta)+Center.X);
Y:=Trunc(Radius*sin(Theta)+Center.Y);
Image.Canvas.LineTo(X,Y);
Theta:=Theta+Step;
end;
end;
- Output:
EasyLang
linewidth 0.4
x = 50
y = 50
while r < 50
line r * cos t + x r * sin t + y
r += 0.05
t += 3
.
FOCAL
1.1 S A=1.5
1.2 S B=2
1.3 S N=250
1.4 F T=1,N; D 2
1.5 X FSKP(2*N)
1.6 Q
2.1 S R=A+B*T; D 3
2.2 X FPT(2*T,X1+512,Y1+390)
2.3 S R=A+B*(T+1); D 4
2.4 X FVEC(2*T+1,X2-X1,Y2-Y1)
3.1 S X1=R*FSIN(.2*T)
3.2 S Y1=R*FCOS(.2*T)
4.1 S X2=R*FSIN(.2*(T+1))
4.2 S Y2=R*FCOS(.2*(T+1))
This program uses FOCAL-11 on a DEC GT40 vector graphics terminal.
Frege
module Archimedean where
import Java.IO
import Prelude.Math
data BufferedImage = native java.awt.image.BufferedImage where
pure native type_3byte_bgr "java.awt.image.BufferedImage.TYPE_3BYTE_BGR" :: Int
native new :: Int -> Int -> Int -> STMutable s BufferedImage
native createGraphics :: Mutable s BufferedImage -> STMutable s Graphics2D
data Color = pure native java.awt.Color where
pure native orange "java.awt.Color.orange" :: Color
pure native white "java.awt.Color.white" :: Color
pure native new :: Int -> Color
data BasicStroke = pure native java.awt.BasicStroke where
pure native new :: Float -> BasicStroke
data RenderingHints = native java.awt.RenderingHints where
pure native key_antialiasing "java.awt.RenderingHints.KEY_ANTIALIASING" :: RenderingHints_Key
pure native value_antialias_on "java.awt.RenderingHints.VALUE_ANTIALIAS_ON" :: Object
data RenderingHints_Key = pure native java.awt.RenderingHints.Key
data Graphics2D = native java.awt.Graphics2D where
native drawLine :: Mutable s Graphics2D -> Int -> Int -> Int -> Int -> ST s ()
native drawOval :: Mutable s Graphics2D -> Int -> Int -> Int -> Int -> ST s ()
native fillRect :: Mutable s Graphics2D -> Int -> Int -> Int -> Int -> ST s ()
native setColor :: Mutable s Graphics2D -> Color -> ST s ()
native setRenderingHint :: Mutable s Graphics2D -> RenderingHints_Key -> Object -> ST s ()
native setStroke :: Mutable s Graphics2D -> BasicStroke -> ST s ()
data ImageIO = mutable native javax.imageio.ImageIO where
native write "javax.imageio.ImageIO.write" :: MutableIO BufferedImage -> String -> MutableIO File -> IO Bool throws IOException
width = 640
center = width `div` 2
roundi = fromIntegral . round
drawGrid :: Mutable s Graphics2D -> ST s ()
drawGrid g = do
g.setColor $ Color.new 0xEEEEEE
g.setStroke $ BasicStroke.new 2
let angle = toRadians 45
margin = 10
numRings = 8
spacing = (width - 2 * margin) `div` (numRings * 2)
forM_ [0 .. numRings-1] $ \i -> do
let pos = margin + i * spacing
size = width - (2 * margin + i * 2 * spacing)
ia = fromIntegral i * angle
multiplier = fromIntegral $ (width - 2 * margin) `div` 2
x2 = center + (roundi (cos ia * multiplier))
y2 = center - (roundi (sin ia * multiplier))
g.drawOval pos pos size size
g.drawLine center center x2 y2
drawSpiral :: Mutable s Graphics2D -> ST s ()
drawSpiral g = do
g.setStroke $ BasicStroke.new 2
g.setColor $ Color.orange
let degrees = toRadians 0.1
end = 360 * 2 * 10 * degrees
a = 0
b = 20
c = 1
drSp theta = do
let r = a + b * theta ** (1 / c)
x = r * cos theta
y = r * sin theta
theta' = theta + degrees
plot g (center + roundi x) (center - roundi y)
when (theta' < end) (drSp (theta' + degrees))
drSp 0
plot :: Mutable s Graphics2D -> Int -> Int -> ST s ()
plot g x y = g.drawOval x y 1 1
main = do
buffy <- BufferedImage.new width width BufferedImage.type_3byte_bgr
g <- buffy.createGraphics
g.setRenderingHint RenderingHints.key_antialiasing RenderingHints.value_antialias_on
g.setColor Color.white
g.fillRect 0 0 width width
drawGrid g
drawSpiral g
f <- File.new "SpiralFrege.png"
void $ ImageIO.write buffy "png" f
Output is here due to Is file uploading blocked forever?
Frink
p = new polyline
g = new graphics
a = 1
b = 1
for theta = 0 to 10 circle step 1 degree
{
r = a + b theta
x = r cos[theta]
y = r sin[theta]
p.addPoint[x,-y]
}
g.add[p]
g.show[]
g.write["ArchimedeanSpiralFrink.svg",800,800]
FutureBasic
_maxPoints = 190
void local fn DoIt
window 1, @"Archimedean Spiral", (0,0,500,500)
WindowSetBackgroundColor( 1, fn ColorBlack )
pen 3, fn ColorRed
float x, y, angle
long i, a = 10, b = 10, x1 = 250, y1 = 250
for i = 0 to _maxPoints - 1
angle = 0.1 * i
x = (a + b * angle) * cos(angle) + 250
y = (a + b * angle) * sin(angle) + 250
line x1,y1 to x,y
x1 = x : y1 = y
next
end fn
fn DoIt
HandleEvents
- Output:
Go
Creates a PNG file using only built-in packages.
package main
import (
"image"
"image/color"
"image/draw"
"image/png"
"log"
"math"
"os"
)
func main() {
const (
width, height = 600, 600
centre = width / 2.0
degreesIncr = 0.1 * math.Pi / 180
turns = 2
stop = 360 * turns * 10 * degreesIncr
fileName = "spiral.png"
)
img := image.NewNRGBA(image.Rect(0, 0, width, height)) // create new image
bg := image.NewUniform(color.RGBA{255, 255, 255, 255}) // prepare white for background
draw.Draw(img, img.Bounds(), bg, image.ZP, draw.Src) // fill the background
fgCol := color.RGBA{255, 0, 0, 255} // red plot
a := 1.0
b := 20.0
for theta := 0.0; theta < stop; theta += degreesIncr {
r := a + b*theta
x := r * math.Cos(theta)
y := r * math.Sin(theta)
img.Set(int(centre+x), int(centre-y), fgCol)
}
imgFile, err := os.Create(fileName)
if err != nil {
log.Fatal(err)
}
defer imgFile.Close()
if err := png.Encode(imgFile, img); err != nil {
imgFile.Close()
log.Fatal(err)
}
}
Haskell
#!/usr/bin/env stack
-- stack --resolver lts-7.0 --install-ghc runghc --package Rasterific --package JuicyPixels
import Codec.Picture( PixelRGBA8( .. ), writePng )
import Graphics.Rasterific
import Graphics.Rasterific.Texture
import Graphics.Rasterific.Transformations
archimedeanPoint a b t = V2 x y
where r = a + b * t
x = r * cos t
y = r * sin t
main :: IO ()
main = do
let white = PixelRGBA8 255 255 255 255
drawColor = PixelRGBA8 0xFF 0x53 0x73 255
size = 800
points = map (archimedeanPoint 0 10) [0, 0.01 .. 60]
hSize = fromIntegral size / 2
img = renderDrawing size size white $
withTransformation (translate $ V2 hSize hSize) $
withTexture (uniformTexture drawColor) $
stroke 4 JoinRound (CapRound, CapRound) $
polyline points
writePng "SpiralHaskell.png" img
Output is here due to Is file uploading blocked forever?
J
require'plot'
'aspect 1' plot (*^)j.0.01*i.1400
Java
import java.awt.*;
import static java.lang.Math.*;
import javax.swing.*;
public class ArchimedeanSpiral extends JPanel {
public ArchimedeanSpiral() {
setPreferredSize(new Dimension(640, 640));
setBackground(Color.white);
}
void drawGrid(Graphics2D g) {
g.setColor(new Color(0xEEEEEE));
g.setStroke(new BasicStroke(2));
double angle = toRadians(45);
int w = getWidth();
int center = w / 2;
int margin = 10;
int numRings = 8;
int spacing = (w - 2 * margin) / (numRings * 2);
for (int i = 0; i < numRings; i++) {
int pos = margin + i * spacing;
int size = w - (2 * margin + i * 2 * spacing);
g.drawOval(pos, pos, size, size);
double ia = i * angle;
int x2 = center + (int) (cos(ia) * (w - 2 * margin) / 2);
int y2 = center - (int) (sin(ia) * (w - 2 * margin) / 2);
g.drawLine(center, center, x2, y2);
}
}
void drawSpiral(Graphics2D g) {
g.setStroke(new BasicStroke(2));
g.setColor(Color.orange);
double degrees = toRadians(0.1);
double center = getWidth() / 2;
double end = 360 * 2 * 10 * degrees;
double a = 0;
double b = 20;
double c = 1;
for (double theta = 0; theta < end; theta += degrees) {
double r = a + b * pow(theta, 1 / c);
double x = r * cos(theta);
double y = r * sin(theta);
plot(g, (int) (center + x), (int) (center - y));
}
}
void plot(Graphics2D g, int x, int y) {
g.drawOval(x, y, 1, 1);
}
@Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
drawGrid(g);
drawSpiral(g);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Archimedean Spiral");
f.setResizable(false);
f.add(new ArchimedeanSpiral(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
JavaScript
ES5
<!-- ArchiSpiral.html -->
<html>
<head><title>Archimedean spiral</title></head>
<body onload="pAS(35,'navy');">
<h3>Archimedean spiral</h3> <p id=bo></p>
<canvas id="canvId" width="640" height="640" style="border: 2px outset;"></canvas>
<script>
// Plotting Archimedean_spiral aev 3/17/17
// lps - number of loops, clr - color.
function pAS(lps,clr) {
var a=.0,ai=.1,r=.0,ri=.1,as=lps*2*Math.PI,n=as/ai;
var cvs=document.getElementById("canvId");
var ctx=cvs.getContext("2d");
ctx.fillStyle="white"; ctx.fillRect(0,0,cvs.width,cvs.height);
var x=y=0, s=cvs.width/2;
ctx.beginPath();
for (var i=1; i<n; i++) {
x=r*Math.cos(a), y=r*Math.sin(a);
ctx.lineTo(x+s,y+s);
r+=ri; a+=ai;
}//fend i
ctx.strokeStyle = clr; ctx.stroke();
}
</script></body></html>
- Output:
Page with Archimedean spiral like ASjs.png. Right-clicking on the canvas you can save spiral as a png-file, for example.
ES6
Assumes the same HTML canvas embedding as above, but is functionally composed. Defines and logs a set of points, before rendering them to canvas.
<html>
<head>
<title>Archimedean spiral</title>
<style>h3 {font-family:sans-serif; color:gray;}</style>
</head>
<body onload="main('red')(15)">
<h3>Archimedean spiral</h3></p>
<canvas id="spiral" width="640" height="640" style="border: 2px outset;"></canvas>
<script>
const main = strColor => intCycles => {
const
ai = 0.05,
ri = 0.1,
cvs = document.getElementById('spiral'),
ctx = cvs.getContext('2d'),
s = cvs.width / 2,
points = enumFromTo(1)(
Math.PI * 2 * intCycles / ai
).map(i => [Math.cos, Math.sin].map(
f => ri * i * f(ai * i) + s
));
return (
console.log(points),
ctx.fillStyle = 'white',
ctx.fillRect(0, 0, cvs.width, cvs.height),
ctx.beginPath(),
points.forEach(xy => ctx.lineTo(...xy)),
ctx.strokeStyle = strColor,
ctx.stroke(),
points
);
};
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = m => n =>
Array.from({
length: 1 + n - m
}, (_, i) => m + i);
</script></body></html>
jq
Works with gojq, the Go implementation of jq
SVG version
def spiral($zero; $turns; $step):
def pi: 1 | atan * 4;
def p2: (. * 100 | round) / 100;
def svg:
400 as $width
| 400 as $height
| 2 as $swidth # stroke
| "blue" as $stroke
| (range($zero; $turns * 2 * pi; $step) as $theta
| (((($theta)|cos) * 2 * $theta + ($width/2)) |p2) as $x
| (((($theta)|sin) * 2 * $theta + ($height/2))|p2) as $y
| if $theta == $zero
then "<path fill='transparent' style='stroke:\($stroke); stroke-width:\($swidth)' d='M \($x) \($y)"
else " L \($x) \($y)"
end),
"' />";
"<svg width='100%' height='100%'
xmlns='http://www.w3.org/2000/svg'>",
svg,
"</svg>" ;
spiral(0; 10; 0.025)
- Output:
PNG version of SVG file (Please feel free to upload to RC)
ASCII Art Version
def spiral($a; $b; $step; $h):
def min($x;$y): if $x <= $y then $x else $y end;
def max($x;$y): if $x <= $y then $y else $x end;
def pi: 1 | atan * 4;
(6 * pi) as $m
| ($h * 1.5) as $w
| { x_min: 9999, y_min: 9999,
x_max: 0, y_max: 0,
arr: [] }
| reduce range($step; $m+$step; $step) as $t (.;
.r = $a + $b * $t
| ((.r * ($t|cos) + $w) | round) as $x
| ((.r * ($t|sin) + $h) | round) as $y
| if $x <= 0 or $y <= 0 then .
elif $x >= 280 then .
elif $y >= 192 then .
else .arr[$x][$y] = "*"
| .x_min = min(.x_min; $x)
| .x_max = max(.x_max; $x)
| .y_min = min(.y_min; $y)
| .y_max = max(.y_max; $y)
end )
# ... and print it
| .arr as $arr
| range(.x_min; .x_max + 1) as $i
| reduce range(.y_min; .y_max+1) as $j ( "";
. + ($arr[$i][$j] // " ") )
| "\(.)\n" ;
spiral(1; 1; 0.02; 96)
- Output:
As for awk.
Julia
using UnicodePlots
spiral(θ, a=0, b=1) = @. b * θ * cos(θ + a), b * θ * sin(θ + a)
x, y = spiral(1:0.1:10)
println(lineplot(x, y))
- Output:
┌────────────────────────────────────────┐ 10 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⠤⠤⠤⠤⠤⠤⡧⠤⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⢀⡠⠔⠊⠉⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠉⠓⠤⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⡠⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠉⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢤⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⡜⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢇⠀⠀⠀⠀⠀⠀⠀│ │⠀⡸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠔⠊⠉⠉⠙⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀│ │⠤⡧⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⡴⠥⠤⠤⠤⠤⠤⡧⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⡼⠤⠤⠤⠤⠤⠤⠄│ │⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠁⠀⠀⠀⠀⠀⠀⠀│ │⠀⢇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢆⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⣀⠜⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠘⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠒⠤⣀⡀⡇⠀⠀⠀⣀⣀⠤⠔⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡏⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ -10 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ └────────────────────────────────────────┘ -10 10
Kotlin
// version 1.1.0
import java.awt.*
import javax.swing.*
class ArchimedeanSpiral : JPanel() {
init {
preferredSize = Dimension(640, 640)
background = Color.white
}
private fun drawGrid(g: Graphics2D) {
g.color = Color(0xEEEEEE)
g.stroke = BasicStroke(2f)
val angle = Math.toRadians(45.0)
val w = width
val center = w / 2
val margin = 10
val numRings = 8
val spacing = (w - 2 * margin) / (numRings * 2)
for (i in 0 until numRings) {
val pos = margin + i * spacing
val size = w - (2 * margin + i * 2 * spacing)
g.drawOval(pos, pos, size, size)
val ia = i * angle
val x2 = center + (Math.cos(ia) * (w - 2 * margin) / 2).toInt()
val y2 = center - (Math.sin(ia) * (w - 2 * margin) / 2).toInt()
g.drawLine(center, center, x2, y2)
}
}
private fun drawSpiral(g: Graphics2D) {
g.stroke = BasicStroke(2f)
g.color = Color.magenta
val degrees = Math.toRadians(0.1)
val center = width / 2
val end = 360 * 2 * 10 * degrees
val a = 0.0
val b = 20.0
val c = 1.0
var theta = 0.0
while (theta < end) {
val r = a + b * Math.pow(theta, 1.0 / c)
val x = r * Math.cos(theta)
val y = r * Math.sin(theta)
plot(g, (center + x).toInt(), (center - y).toInt())
theta += degrees
}
}
private fun plot(g: Graphics2D, x: Int, y: Int) {
g.drawOval(x, y, 1, 1)
}
override fun paintComponent(gg: Graphics) {
super.paintComponent(gg)
val g = gg as Graphics2D
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
drawGrid(g)
drawSpiral(g)
}
}
fun main(args: Array<String>) {
SwingUtilities.invokeLater {
val f = JFrame()
f.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
f.title = "Archimedean Spiral"
f.isResizable = false
f.add(ArchimedeanSpiral(), BorderLayout.CENTER)
f.pack()
f.setLocationRelativeTo(null)
f.isVisible = true
}
}
Lambdatalk
1) from polar to cartesian coordinates
x = r*cos(t) = (a+b*t)*cos(t)
y = r*sin(t) = (a+b*t)*sin(t)
2) define the curve
{def CURVE
{lambda {:a :b :t}
{* {+ :a {* :b :t}} {cos :t}}
{* {+ :a {* :b :t}} {sin :t}}
}}
-> CURVE
3) and draw it using SVG
{{SVG 580}
{g {AXES 580 580}
{polyline {@ points="{S.map {CURVE 5 4}
{S.serie 0 {* 10 {PI}} 0.1}}"
{stroke red 3}}
}}}
The ouput can be seen in http://lambdaway.free.fr/lambdawalks/?view=archimedian_spiral
Lua
a=1
b=2
cycles=40
step=0.001
x=0
y=0
function love.load()
x = love.graphics.getWidth()/2
y = love.graphics.getHeight()/2
end
function love.draw()
love.graphics.print("a="..a,16,16)
love.graphics.print("b="..b,16,32)
for i=0,cycles*math.pi,step do
love.graphics.points(x+(a + b*i)*math.cos(i),y+(a + b*i)*math.sin(i))
end
end
M2000 Interpreter
module Archimedean_spiral {
smooth on ' enable GDI+
def r(θ)=5+3*θ
cls #002222,0
pen #FFFF00
refresh 5000
every 1000 {
\\ redifine window (console width and height) and place it to center (symbol ;)
Window 12, random(10, 18)*1000, random(8, 12)*1000;
move scale.x/2, scale.y/2
let N=2, k1=pi/120, k=k1, op=5, op1=1
for i=1 to int(1200*min.data(scale.x, scale.y)/18000)
pen op
swap op, op1
Width 3 {draw angle k, r(k)*n}
k+=k1
next
refresh 5000
\\ press space to exit loop
if keypress(32) then exit
}
pen 14
cls 5
refresh 50
}
Archimedean_spiral
Maple
plots[polarplot](1+2*theta, theta = 0 .. 6*Pi)
Mathematica/Wolfram Language
The built-in function PolarPlot easily creates the desired plot
With[{a = 5, b = 4}, PolarPlot[a + b t, {t, 0, 10 Pi}]]
MATLAB
a = 1;
b = 1;
turns = 2;
theta = 0:0.1:2*turns*pi;
polarplot(theta, a + b*theta);
Maxima
Using draw package
archi_spi(a,b):=wxdraw2d(nticks=200,polar(a+b*theta,theta,1,10*%pi))$
archi_spi(1,1);
MiniScript
For use with the Mini Micro.
clear
x0 = gfx.width / 2
y0 = gfx.height / 2
gfx.clear color.white
for t in range(0, 70 * pi, 0.1)
r = 3.2+ 1.5 * t
x = r * cos(t) + gfx.width / 2
y = r * sin(t) + gfx.height / 2
gfx.line x0, y0, x, y, color.black,2
x0 = x; y0 = y
end for
Alternative version using a Turtle library included with the Mini Micro.
import "turtle"
radToDegrees = function(rad)
return 180 * rad / pi
end function
clear
print Turtle.displayNum
display(Turtle.displayNum).clear
t = new Turtle
for i in range(0, 50, 0.04)
t.forward i
t.left radToDegrees(pi/20)
end for
Nim
import math
import gintro/[glib, gobject, gtk, gio, cairo]
const
Width = 601
Height = 601
Limit = 12 * math.PI
Origin = (x: float(Width div 2), y: float(Height div 2))
B = floor((Width div 2) / Limit)
#---------------------------------------------------------------------------------------------------
proc draw(area: DrawingArea; context: Context) =
## Draw the spiral.
var theta = 0.0
var delta = 0.01
var (prevx, prevy) = Origin
# Clear the region.
context.moveTo(0, 0)
context.setSource(0.0, 0.0, 0.0)
context.paint()
# Draw the spiral.
context.setSource(1.0, 1.0, 0.0)
context.moveTo(Origin.x, Origin.y)
while theta < Limit:
let r = B * theta
let x = Origin.x + r * cos(theta) # X-coordinate on drawing area.
let y = Origin.y + r * sin(theta) # Y-coordinate on drawing area.
context.lineTo(x, y)
context.stroke()
# Set data for next round.
context.moveTo(x, y)
prevx = x
prevy = y
theta += delta
#---------------------------------------------------------------------------------------------------
proc onDraw(area: DrawingArea; context: Context; data: pointer): bool =
## Callback to draw/redraw the drawing area contents.
area.draw(context)
result = true
#---------------------------------------------------------------------------------------------------
proc activate(app: Application) =
## Activate the application.
let window = app.newApplicationWindow()
window.setSizeRequest(Width, Height)
window.setTitle("Archimedean spiral")
# Create the drawing area.
let area = newDrawingArea()
window.add(area)
# Connect the "draw" event to the callback to draw the spiral.
discard area.connect("draw", ondraw, pointer(nil))
window.showAll()
#———————————————————————————————————————————————————————————————————————————————————————————————————
let app = newApplication(Application, "Rosetta.spiral")
discard app.connect("activate", activate)
discard app.run()
PARI/GP
Note: cartes2() can be found here on PARI/GP page.
\\ The Archimedean spiral
\\ ArchiSpiral() - Where: lps is a number of loops, c is a direction 0/1
\\ (counter-clockwise/clockwise). 6/6/16 aev
\\ Note: cartes2() can be found here on
\\ http://rosettacode.org/wiki/Polyspiral#PARI.2FGP page.
ArchiSpiral(size,lps,c=0)={
my(a=.0,ai=.1,r=.0,ri=.1,as=lps*2*Pi,n=as/ai,x,y,vc,vx=List(.0),vy=vx);
if(c<0||c>1, c=0); if(c, ai*=-1);
print(" *** The Archimedean spiral: size=",size," loops=",lps," c=",c);
for(i=1, n, vc=cartes2(r,a); x=vc[1]; y=vc[2];
listput(vx,x); listput(vy,y);
r+=ri; a+=ai;
);\\fend i
plothraw(Vec(vx),Vec(vy));
}
{\\ Executing:
ArchiSpiral(640,5); \\ArchiSpiral1.png
ArchiSpiral(640,5,1); \\ArchiSpiral2.png
}
- Output:
> ArchiSpiral(640,5); \\ArchiSpiral1.png *** The Archimedean spiral: size=640 loops=5 c=0 > ArchiSpiral(640,5,1); \\ArchiSpiral2.png *** The Archimedean spiral: size=640 loops=5 c=1
PascalABC.NET
uses PlotWPF,GraphWPF;
begin
Window.SetSize(600,600);
var seq := Range(0,20,0.1);
var xx := seq.Select(t -> t * Cos(t));
var yy := seq.Select(t -> t * Sin(t));
LineGraphWPF.Create(xx,yy,Colors.Black);
end.
Perl
use Imager;
use constant PI => 3.14159265;
my ($w, $h) = (400, 400);
my $img = Imager->new(xsize => $w, ysize => $h);
for ($theta = 0; $theta < 52*PI; $theta += 0.025) {
$x = $w/2 + $theta * cos($theta/PI);
$y = $h/2 + $theta * sin($theta/PI);
$img->setpixel(x => $x, y => $y, color => '#FF00FF');
}
$img->write(file => 'Archimedean-spiral.png');
Phix
You can run this online here.
-- -- demo\rosetta\Archimedean_spiral.exw -- =================================== -- with javascript_semantics include pGUI.e Ihandle dlg, canvas cdCanvas cddbuffer, cdcanvas function redraw_cb(Ihandle /*ih*/) integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE"), a = 0, b = 5, cx = floor(w/2), cy = floor(h/2) cdCanvasActivate(cddbuffer) for deg=0 to 360*7 do atom rad = deg*PI/180, r = rad*b + a integer x = cx + floor(r*cos(rad)), y = cy + floor(r*sin(rad)) cdCanvasPixel(cddbuffer, x, y, #00FF00) end for 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_WHITE) cdCanvasSetForeground(cddbuffer, CD_RED) return IUP_DEFAULT end function procedure main() IupOpen() canvas = IupCanvas("RASTERSIZE=500x500") -- initial size IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"), "ACTION", Icallback("redraw_cb")}) dlg = IupDialog(canvas,`TITLE="Archimedean spiral"`) IupShow(dlg) IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation if platform()!=JS then IupMainLoop() IupClose() end if end procedure main()
Processing
Processing examples are animated, with a new point / segment added each draw() frame. Because Processing includes multiple built-in ways for drawing in rotating frames of reference, there are several ways to approach the Archimedean spiral problem.
Java mode
with points
When drawn with points the rotation must be very small, and initially the animation is very slow. This is because the points will move further and further apart as the radius increases.
float x, y;
float theta;
float rotation;
void setup() {
size(300, 300);
theta = 0;
rotation = 0.1;
background(255);
}
void draw() {
translate(width/2.0, height/2.0);
x = theta*cos(theta/PI);
y = theta*sin(theta/PI);
point(x, y);
theta = theta + rotation;
// check restart
if (x>width/2.0) frameCount=-1;
}
with points, rotated
Rotates the canvas matrix using the built-in rotate() and draws a simple point, rather than computing rotated coordinates with sin()/cos().
float theta;
float rotation;
void setup() {
size(300, 300);
theta = 0;
rotation = 0.1;
background(255);
}
void draw() {
translate(width/2.0, height/2.0);
theta += rotation;
rotate(theta/PI);
point(theta, 0);
// check restart
if (theta>width/2.0) frameCount=-1;
}
with points, vector
Rotates a vector object of increasing magnitude using the built-in PVector and draws its point, rather than computing rotated coordinates with sin()/cos().
PVector pv;
float rotation;
void setup() {
size(300, 300);
rotation = 0.1;
pv = new PVector(rotation, 0);
background(255);
}
void draw() {
translate(width/2.0, height/2.0);
pv.setMag(pv.mag()+rotation);
println(pv.mag());
pv.rotate(rotation/PI);
point(pv.x, pv.y);
// check restart
if (pv.mag()>width/2.0) frameCount=-1;
}
with line segments
Draw each new line segments anchored to the previous point in order to keep the spiral visually connected no matter how much the radius expands.
float px, py, x, y;
float theta;
float rotation;
void setup() {
size(300, 300);
px = py = x = y = theta = 0;
rotation = 0.1;
background(255);
}
void draw() {
translate(width/2.0, height/2.0);
x = theta*cos(theta/PI);
y = (theta)*sin(theta/PI);
line(x, y, px, py);
theta = theta + rotation;
px = x;
py = y;
// check restart
if (px>width/2.0) frameCount=-1;
}
with line segments, rotated
Uses the built-in rotate() and screenX() to rotate the frame of reference and then recover the rotated screen position of each next point. Draw each new line segments anchored to the previous point in order to keep the spiral visually connected no matter how much the radius expands.
float x, y, px, py;
float theta;
float rotation;
void setup() {
size(300, 300);
x = y = px = py = theta = 0;
rotation = 0.1;
background(255);
}
void draw() {
// find coordinates with rotating reference frame
pushMatrix();
rotate(theta/PI);
x = screenX(theta, 0);
y = screenY(theta, 0);
popMatrix();
translate(width/2.0, height/2.0);
theta += rotation;
line(px, py, x, y);
px = x;
py = y;
if (theta>width/2.0) frameCount=-1; // start over
}
Processing Python mode
with points
When drawn with points the rotation must be very small, and initially the animation is very slow. This is because the points will move further and further apart as the radius increases.
theta = 0
rotation = 0.1
def setup():
size(300, 300)
background(255)
def draw():
global theta
translate(width / 2.0, height / 2.0)
x = theta * cos(theta / PI)
y = theta * sin(theta / PI)
point(x, y)
theta = theta + rotation
# check restart
if x > width / 2.0:
background(255)
theta = 0
Python
Using the turtle module.
from turtle import *
from math import *
color("blue")
down()
for i in range(200):
t = i / 20 * pi
x = (1 + 5 * t) * cos(t)
y = (1 + 5 * t) * sin(t)
goto(x, y)
up()
done()
Quackery
[ $ "turtleduck.qky" loadfile ] now!
turtle
20 frames
0 n->v
900 times
[ 2dup walk
1 20 v+
1 36 turn ]
2drop
1 frames
- Output:
R
with(list(s=seq(0, 10 * pi, length.out=500)),
plot((1 + s) * exp(1i * s), type="l"))
Racket
File:Archemedian-spiral-racket.png
#lang racket/base
(require plot
racket/math)
;; x and y bounds set to centralise the circle
(define (archemedian-spiral-renderer2d a b θ/τ-max
#:samples (samples (line-samples)))
(define (f θ) (+ a (* b θ)))
(define max-dim (+ a (* θ/τ-max 2 pi b)))
(polar f
0 (* θ/τ-max 2 pi)
#:x-min (- max-dim)
#:x-max max-dim
#:y-min (- max-dim)
#:y-max max-dim
#:samples samples))
(plot (list (archemedian-spiral-renderer2d 0.0 24 4)))
;; writes to a file so hopefully, I can post it to RC...
(plot-file (list (archemedian-spiral-renderer2d 0.0 24 4))
"images/archemidian-spiral-racket.png")
Raku
(formerly Perl 6)
use Image::PNG::Portable;
my ($w, $h) = (400, 400);
my $png = Image::PNG::Portable.new: :width($w), :height($h);
(0, .025 ... 52*π).race.map: -> \Θ {
$png.set: |((cis( Θ / π ) * Θ).reals »+« ($w/2, $h/2))».Int, 255, 0, 255;
}
$png.write: 'Archimedean-spiral-perl6.png';
REXX
This REXX version allows the user to specify (or override) the various constants used to calculate and display the spiral (plot).
Note: the value of a doesn't mean that much as the plot is automatically centered.
/*REXX pgm plots several cycles (half a spiral) of the Archimedean spiral (ASCII plot).*/
parse arg cy a b inc chr . /*obtain optional arguments from the CL*/
if cy=='' | cy=="," then cy= 3 /*Not specified? Then use the default.*/
if a=='' | a=="," then a= 1 /* " " " " " " */
if b=='' | b=="," then b= 9 /* " " " " " " */
if inc=='' | inc=="," then inc= 0.02 /* " " " " " " */
if chr=='' | chr=="," then chr= '∙' /* " " " " " " */
if length(chr)==3 then chr= d2c(chr) /*plot character coded in decimal? */
if length(chr)==2 then chr= x2c(chr) /* " " " " hexadecimal? */
cy= max(2, cy); LOx= . /*set the LOx variable (a semaphore).*/
parse value scrsize() with sd sw . /*get the size of the terminal screen. */
w= sw - 1 ; mw= w * (cy-1) * 4 /*set useable width; max width for calc*/
h= sd - 1 + cy*10; mh= h * (cy-1) /* " " depth; " depth " " */
@.= /*initialize the line based plot field.*/
do t=1 to pi()*cy by inc /*calc all the coördinates for spiral. */
r= a + b* t /* " " " R " " */
x= w + r*cos(t); xx= x % 2 /* " " " X " " */
y= h + r*sin(t); yy= y % 2 /* " " " Y " " */
if x<0 | y<0 | x>mw | y>mh then iterate /*Is X or Y out of bounds? Then skip.*/
if LOx==. then do; LOx= xx; HIx= xx; LOy= yy; HIy= yy
end /* [↑] find the minimums and maximums.*/
LOx= min(LOx, xx); HIx= max(HIx, xx) /*determine the X MIN and MAX. */
LOy= min(LOy, yy); HIy= max(HIy, yy) /* " " Y " " " */
@.yy= overlay(chr, @.yy, xx+1) /*assign the plot character (glyph). */
end /*t*/
call plot /*invoke plotting subroutine (to term).*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
pi: pi=3.1415926535897932384626433832795028841971693993751058209749445923078; return pi
plot: do row=HIy to LOy by -1; say substr(@.row, LOx+1); end; return
r2r: return arg(1) // (pi() * 2) /*normalize radians ───► a unit circle.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
cos: procedure; parse arg x; x= r2r(x); _= 1; a= abs(x); hpi= pi * .5
numeric fuzz min(6, digits() - 3); if a=pi then return -1
if a=hpi | a=hpi*3 then return 0 if a=pi / 3 then return .5
if a=pi * 2 / 3 then return -.5; q= x*x; z= 1
do k=2 by 2 until p=z; p= z; _= -_ *q/(k*k-k); z= z+_; end; return z
/*──────────────────────────────────────────────────────────────────────────────────────*/
sin: procedure; parse arg x; x= r2r(x); _= x; numeric fuzz min(5, max(1, digits() -3))
if x=pi * .5 then return 1; if x==pi*1.5 then return -1
if abs(x)=pi | x=0 then return 0; q= x*x; z= x
do k=2 by 2 until p=z; p= z; _= -_ *q/(k*k+k); z= z+_; end; return z
- output when using the following inputs: 13 , 5 , db
(Output is shown at 1/20 size.)
█ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ ██ █ ██ █ █ █ ██ █ █ ██ █ █ █ █ █ ██ █ ██ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ ██ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ███ ███ ███ ███ ███ █ █ █ █ ███ ███ █ █ █ █ █ ██ ██ █ █ █ █ █ ██ ██ █ █ █ ██ █ ██ █ █ █ ██ █ █ █ █ ██ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █████ █ █ █ █ █ ███████ ███████ █ █ █ █ █ ████ ████ █ █ █ █ █ ███ ████ █ █ █ █ ███ ██ █ █ █ █ █ █ ██ ███ █ █ █ ██ ██ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ ██ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ ████████████ █ █ █ █ █ █ █████ ████ ██ █ █ █ █ ███ ████ █ █ █ █ █ █ █ ███ ███ █ █ █ █ █ █ █ ██ ███ █ █ █ █ ██ ██ █ █ █ █ █ █ ███ ██ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ ██ █ ██ █ █ █ █ █ █ █ ██ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ ██ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ ████████████ █ █ █ █ █ █ ███ ███ █ █ █ █ █ █ █ █ █ ██ ███ █ ██ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ ██ ██ ██ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ ██ █████ █ █ █ █ █ █ █ █ █ ███ ███ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ ██ ██ ██ █ █ █ █ █ █ █ ███ ███ ██ █ █ █ █ █ █ █ █ █ █████ █████ █ █ █ █ █ █ █ █ ███ ██ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ ██ ██ ██ █ █ █ █ █ █ ██ ██ ██ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ ██ ███ █ █ █ █ █ ██ ███ ████ ██ █ █ █ █ █ █ ████ ████ █ █ █ █ █ █ █ █████████████ █ █ █ █ █ █ ██ █ █ █ █ █ ██ █ █ █ █ █ █ █ ██ █ █ █ █ ██ █ █ █ █ ██ █ █ █ █ █ █ █ ██ █ █ █ █ ██ █ ██ █ █ █ █ █ ██ █ █ █ █ █ ██ ██ █ █ █ █ █ ██ █ █ █ █ █ █ █ ███ ███ █ █ █ ██ ██ █ █ █ █ █ █ ███ ████ █ █ █ █ ██ ████ ███ █ █ █ █ ██████ ██████ █ █ █ █ █ ██████████ █ █ █ █ ██ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ ██ ██ █ █ █ ██ █ █ █ █ █ █ ██ ██ █ █ █ ██ ██ █ █ █ ███ ███ █ █ █ █ ██ █ ███ █ █ █ ████ ███ █ █ █ █ ██ ████ ██████ ██████ █ █ █ █ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ ██ █ ██ █ █ █ ██ █ █ ██ █ █ █ █ █ ██ █ █ █ █ ██ █ █ ██ ██ █ █ ██ █ ██ █ █ █ ██ █ ██ ██ █ █ █ ██ ██ ██ ██ ██ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ █ █ █ ██ ██ █ █ █ █ ██ █ ██ █ █ █ ██ █ █ █ █ █ █ █ ██ █ █ █ █
Ring
/*
+---------------------------------------------------------------------------------------------------------
+ Program Name : Archimedean spiral
+---------------------------------------------------------------------------------------------------------
*/
Load "guilib.ring"
horzSize = 400
vertSize = 400
counter = 0 ### cycle thru colors
colorRed = new qcolor() { setrgb(255,000,000,255) }
colorGreen = new qcolor() { setrgb(000,255,000,255) }
colorBlue = new qcolor() { setrgb(000,000,255,255) }
colorYellow = new qcolor() { setrgb(255,255,000,255) }
penUseR = new qpen() { setcolor(colorRed) setwidth(1) }
penUseG = new qpen() { setcolor(colorGreen) setwidth(1) }
penUseB = new qpen() { setcolor(colorBlue) setwidth(1) }
penUseY = new qpen() { setcolor(colorYellow) setwidth(1) }
deg2rad = atan(1) * 4 / 180
screensize = 600
turns = 5
halfscrn = screensize / 2
sf = (turns * (screensize - 100)) / halfscrn
x = 1
y = 1
r = 0
inc = 0.50 ### control increment speed of r
New qapp
{
win1 = new qwidget()
{
setwindowtitle("Draw Spiral")
setgeometry(100,100,600,600)
label1 = new qlabel(win1)
{
setgeometry(10,10,600,600)
settext("")
}
Canvas = new qlabel(win1)
{
MonaLisa = new qPixMap2( 600,600)
color = new qcolor(){ setrgb(255,0,0,255) }
daVinci = new qpainter()
{
begin(MonaLisa)
penUse = new qpen() { setcolor(colorRed) setwidth(1) }
setpen(penUseR)
#endpaint() ### This will Stop the Painting
}
setpixmap(MonaLisa)
}
oTimer = new qTimer(win1)
{
setinterval(1) ### 1 millisecond
settimeoutevent("DrawCounter()")
start()
}
show() ### Will show Painting ONLY after exec
}
exec()
}
###====================================================
Func DrawCounter()
x = cos(r * deg2rad) * r / sf
y = sin(r * deg2rad) * r / sf
r += inc ### 0.20 fast, 0.90 slow
if r >= turns * 360
r = inc
x = 1
y = 1
counter++
whichColor = counter % 4
See "whichColor: "+ whichColor +nl
if whichColor = 0 daVinci.setpen(penUseR) ok
if whichColor = 1 daVinci.setpen(penUseG) ok
if whichColor = 2 daVinci.setpen(penUseB) ok
if whichColor = 3 daVinci.setpen(penUseY) ok
ok
hpoint = halfscrn + x
ypoint = halfscrn - y
daVinci.drawpoint(hpoint, ypoint)
Canvas.setpixmap(MonaLisa) ### Need this setpixmap to display imageLabel
win1.show() ### Need this show to display imageLabel
return
RPL
« → a b
« -20 20 DUP2 XRNG YRNG
POLAR RAD 'a+b*t' STEQ { t 0 18.9 } INDEP
ERASE DRAW { } PVIEW
{ EQ PPAR } PURGE
» » 'ARCHI' STO
1 1 ARCHI
Ruby
JRubyArt is an implementation of Processing in ruby, that uses JRuby to provide the interoperability with the java libraries.
INCR = 0.1
attr_reader :x, :theta
def setup
sketch_title 'Archimedian Spiral'
@theta = 0
@x = 0
background(255)
translate(width / 2.0, height / 2.0)
begin_shape
(0..50*PI).step(INCR) do |theta|
@x = theta * cos(theta / PI)
curve_vertex(x, theta * sin(theta / PI))
end
end_shape
end
def settings
size(300, 300)
end
Rust
#[macro_use(px)]
extern crate bmp;
use bmp::{Image, Pixel};
use std::f64;
fn main() {
let width = 600u32;
let half_width = (width / 2) as i32;
let mut img = Image::new(width, width);
let draw_color = px!(255, 128, 128);
// Constants defining the spiral size.
let a = 1.0_f64;
let b = 9.0_f64;
// max_angle = number of spirals * 2pi.
let max_angle = 5.0_f64 * 2.0_f64 * f64::consts::PI;
let mut theta = 0.0_f64;
while theta < max_angle {
theta = theta + 0.002_f64;
let r = a + b * theta;
let x = (r * theta.cos()) as i32 + half_width;
let y = (r * theta.sin()) as i32 + half_width;
img.set_pixel(x as u32, y as u32, draw_color);
}
// Save the image
let _ = img.save("archimedean_spiral.bmp").unwrap_or_else(|e| panic!("Failed to save: {}", e));
}
SAS
data xy;
h=constant('pi')/40;
do i=0 to 400;
t=i*h;
x=(1+t)*cos(t);
y=(1+t)*sin(t);
output;
end;
keep x y;
run;
proc sgplot;
series x=x y=y;
run;
Scala
Java Swing Interoperability
object ArchimedeanSpiral extends App {
SwingUtilities.invokeLater(() =>
new JFrame("Archimedean Spiral") {
class ArchimedeanSpiral extends JPanel {
setPreferredSize(new Dimension(640, 640))
setBackground(Color.white)
private def drawGrid(g: Graphics2D): Unit = {
val (angle, margin, numRings) = (toRadians(45), 10, 8)
val w = getWidth
val (center, spacing) = (w / 2, (w - 2 * margin) / (numRings * 2))
g.setColor(new Color(0xEEEEEE))
for (i <- 0 until numRings) {
val pos = margin + i * spacing
val size = w - (2 * margin + i * 2 * spacing)
g.drawOval(pos, pos, size, size)
val ia = i * angle
val x2 = center + (cos(ia) * (w - 2 * margin) / 2).toInt
val y2 = center - (sin(ia) * (w - 2 * margin) / 2).toInt
g.drawLine(center, center, x2, y2)
}
}
private def drawSpiral(g: Graphics2D): Unit = {
val (degrees: Double, center) = (toRadians(0.1), getWidth / 2)
val (a, b, c, end) = (0, 20, 1, 360 * 2 * 10 * degrees)
def plot(g: Graphics2D, x: Int, y: Int): Unit = g.drawOval(x, y, 1, 1)
def iter(theta: Double): Double = {
if (theta < end) {
val r = a + b * pow(theta, 1 / c)
val x = r * cos(theta)
val y = r * sin(theta)
plot(g, (center + x).toInt, (center - y).toInt)
iter(theta + degrees)
} else theta
}
g.setStroke(new BasicStroke(2))
g.setColor(Color.orange)
iter(0)
}
override def paintComponent(gg: Graphics): Unit = {
super.paintComponent(gg)
val g = gg.asInstanceOf[Graphics2D]
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
drawGrid(g)
drawSpiral(g)
}
}
add(new ArchimedeanSpiral, BorderLayout.CENTER)
pack()
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
setLocationRelativeTo(null)
setResizable(false)
setVisible(true)
}
)
}
Scheme
(import (scheme base)
(scheme complex)
(rebottled pstk))
; settings for spiral
(define *resolution* 0.01)
(define *count* 2000)
(define *a* 10)
(define *b* 10)
(define *center*
(let ((size 200)) ; change this to alter size of display
(* size 1+i)))
(define (draw-spiral canvas)
(define (coords theta)
(let ((r (+ *a* (* *b* theta))))
(make-polar r theta)))
;
(do ((i 0 (+ i 1))) ; loop to draw spiral
((= i *count*) )
(let ((c (+ (coords (* i *resolution*)) *center*)))
(canvas 'create 'line
(real-part c) (imag-part c)
(+ 1 (real-part c)) (imag-part c)))))
(let ((tk (tk-start)))
(tk/wm 'title tk "Archimedean Spiral")
(let ((canvas (tk 'create-widget 'canvas)))
(tk/pack canvas)
(canvas 'configure
'height: (* 2 (real-part *center*))
'width: (* 2 (imag-part *center*)))
(draw-spiral canvas))
(tk-event-loop tk))
Scilab
a = 3;
b = 2;
theta = linspace(0,10*%pi,1000);
r = a + b .* theta;
//1. Plot using polar coordinates
scf(1);
polarplot(theta,r);
//2. Plot using rectangular coordinates
//2.1 Convert coordinates using Euler's formula
z = r .* exp(%i .* theta);
x = real(z);
y = imag(z);
scf(2);
plot2d(x,y);
Seed7
$ include "seed7_05.s7i";
include "draw.s7i";
include "keybd.s7i";
const proc: main is func
local
const float: xCenter is 117.0;
const float: yCenter is 139.0;
const float: maxTheta is 10.0 * PI;
const float: delta is 0.01;
const float: a is 1.0;
const float: b is 7.0;
var float: theta is 0.0;
var float: radius is 0.0;
begin
screen(256, 256);
clear(curr_win, black);
KEYBOARD := GRAPH_KEYBOARD;
while theta <= maxTheta do
radius := a + b * theta;
point(round(xCenter + radius * cos(theta)),
round(yCenter - radius * sin(theta)), white);
theta +:= delta;
end while;
flushGraphic;
ignore(getc(KEYBOARD));
end func;
Sidef
require('Imager')
define π = Num.pi
var (w, h) = (400, 400)
var img = %O<Imager>.new(xsize => w, ysize => h)
for Θ in (0 .. 52*π -> by(0.025)) {
img.setpixel(
x => floor(cos(Θ / π)*Θ + w/2),
y => floor(sin(Θ / π)*Θ + h/2),
color => [255, 0, 0]
)
}
img.write(file => 'Archimedean_spiral.png')
Output image: Archimedean spiral
Stata
clear all
scalar h=_pi/40
set obs 400
gen t=_n*h
gen x=(1+t)*cos(t)
gen y=(1+t)*sin(t)
line y x
Tcl
This creates a little Tk GUI where you can interactively enter values for `a` and `b`. The spiral will be re-drawn automatically thanks to `trace`:
package require Tk
# create widgets
canvas .canvas
frame .controls
ttk::label .legend -text " r = a + b θ "
ttk::label .label_a -text "a ="
ttk::entry .entry_a -textvariable a
ttk::label .label_b -text "a ="
ttk::entry .entry_b -textvariable b
button .button -text "Redraw" -command draw
# layout
grid .canvas .controls -sticky nsew
grid .legend - -sticky ns -in .controls
grid .label_a .entry_a -sticky nsew -in .controls
grid .label_b .entry_b -sticky nsew -in .controls
grid .button - -sticky ns -in .controls
# make the canvas resize with the window
grid columnconfigure . 0 -weight 1
grid rowconfigure . 0 -weight 1
# spiral parameters:
set a .2
set b .05
proc draw {} {
variable a
variable b
# make sure inputs are valid:
if {![string is double $a] || ![string is double $b]} return
if {$a == 0 || $b == 0} return
set w [winfo width .canvas]
set h [winfo height .canvas]
set r 0
set pi [expr {4*atan(1)}]
set step [expr {$pi / $w}]
for {set t 0} {$r < 2} {set t [expr {$t + $step}]} {
set r [expr {$a + $b * $t}]
set y [expr {sin($t) * $r}]
set x [expr {cos($t) * $r}]
# transform to canvas co-ordinates
set y [expr {entier((1+$y)*$h/2)}]
set x [expr {entier((1+$x)*$w/2)}]
lappend coords $x $y
}
.canvas delete all
set id [.canvas create line $coords -fill red]
}
# draw whenever parameters are changed
# ";#" so extra trace arguments are ignored
trace add variable a write {draw;#}
trace add variable b write {draw;#}
wm protocol . WM_DELETE_WINDOW exit ;# exit when window is closed
update ;# lay out widgets before trying to draw
draw
vwait forever ;# go into event loop until window is closed
Wren
import "graphics" for Canvas, Color
import "dome" for Window
class Game {
static init() {
Window.title = "Archimedean Spiral"
__width = 400
__height = 400
Canvas.resize(__width, __height)
Window.resize(__width, __height)
var col = Color.red
spiral(col)
}
static spiral(col) {
var theta = 0
while (theta < 52 * Num.pi) {
var x = ((theta/Num.pi).cos * theta + __width/2).truncate
var y = ((theta/Num.pi).sin * theta + __height/2).truncate
Canvas.pset(x, y, col)
theta = theta + 0.025
}
}
static update() {}
static draw(dt) {}
}
- Output:
File:Wren-Archimedean spiral.png
XPL0
Looks a lot like the C++ image.
real A, B, R, T, X, Y;
[SetVid($12); \set 640x480 graphics
A:= 0.0; B:= 3.0; T:= 0.0;
Move(320, 240); \start at center of screen
repeat R:= A + B*T;
X:= R*Cos(T); Y:= R*Sin(T);
Line(fix(X)+320, 240-fix(Y), 4\red\);
T:= T + 0.03; \increase angle (Theta)
until T >= 314.159; \50 revs
]
zkl
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
fcn archimedeanSpiral(a,b,circles){
w,h:=640,640; centerX,centerY:=w/2,h/2;
bitmap:=PPM(w+1,h+1,0xFF|FF|FF); // White background
foreach deg in ([0.0 .. 360*circles]){
rad:=deg.toRad();
r:=rad*b + a;
x,y:=r.toRectangular(rad);
bitmap[centerX + x, centerY + y] = 0x00|FF|00; // Green dot
}
bitmap.writeJPGFile("archimedeanSpiral.jpg");
}(0,5,7);
- Programming Tasks
- Solutions by Programming Task
- Action!
- Ada
- SDLAda
- ALGOL 68
- ALGOL W
- Amazing Hopper
- APL
- AutoHotkey
- AWK
- BASIC
- AmigaBASIC
- Applesoft BASIC
- BASIC256
- BBC BASIC
- Pages with broken file links
- Chipmunk Basic
- Commodore BASIC
- FreeBASIC
- GW-BASIC
- IS-BASIC
- Locomotive Basic
- PureBasic
- Run BASIC
- QBasic
- Sinclair ZX81 BASIC
- VBA
- Yabasic
- BQN
- C
- C sharp
- C++
- Clojure
- Common Lisp
- Craft Basic
- Delphi
- Types,ExtCtrls,Graphics
- EasyLang
- FOCAL
- Frege
- Frink
- FutureBasic
- Go
- Haskell
- Juicy.Pixels
- Rasterific
- J
- Java
- JavaScript
- Jq
- Julia
- Kotlin
- Lambdatalk
- Lua
- LÖVE
- M2000 Interpreter
- Maple
- Mathematica
- Wolfram Language
- MATLAB
- Maxima
- MiniScript
- Nim
- Gintro
- PARI/GP
- PascalABC.NET
- Perl
- Phix
- Phix/pGUI
- Phix/online
- Processing
- Processing Python mode
- Python
- Quackery
- R
- Racket
- Raku
- REXX
- Ring
- RPL
- Ruby
- RubyGems
- JRubyArt
- Rust
- SAS
- Scala
- Scheme
- Scheme/PsTk
- Scilab
- Seed7
- Sidef
- Stata
- Tcl
- Wren
- DOME
- XPL0
- Zkl