Polyspiral: Difference between revisions
m (→{{header|Wren}}: Changed to Wren S/H) |
|||
(19 intermediate revisions by 15 users not shown) | |||
Line 34: | Line 34: | ||
<br><br> |
<br><br> |
||
=={{header|Action!}}== |
|||
{{libheader|Action! Tool Kit}} |
|||
{{libheader|Action! Real Math}} |
|||
<syntaxhighlight lang="action!">INCLUDE "H6:REALMATH.ACT" |
|||
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 i,angle,x,y,tmp |
|||
REAL rx,ry,len,dlen,r1,r2,r3,r256 |
|||
IntToReal(x0,rx) |
|||
IntToReal(y0,ry) |
|||
ValR("1.9",len) |
|||
ValR("1.14",dlen) |
|||
IntToReal(256,r256) |
|||
angle=0 |
|||
Plot(x0,y0) |
|||
FOR i=1 TO 150 |
|||
DO |
|||
tmp=Cos(angle) |
|||
IntToRealForNeg(tmp,r1) |
|||
RealDiv(r1,r256,r2) |
|||
RealMult(r2,len,r1) |
|||
RealAdd(rx,r1,r2) |
|||
RealAssign(r2,rx) |
|||
tmp=Sin(angle) |
|||
IntToRealForNeg(tmp,r1) |
|||
RealDiv(r1,r256,r2) |
|||
RealMult(r2,len,r1) |
|||
RealAdd(ry,r1,r2) |
|||
RealAssign(r2,ry) |
|||
x=RealToInt(rx) |
|||
y=RealToInt(ry) |
|||
DrawTo(x,y) |
|||
RealAdd(len,dlen,r1) |
|||
RealAssign(r1,len) |
|||
angle==+123 |
|||
IF angle>360 THEN |
|||
angle==-360 |
|||
FI |
|||
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/Polyspiral.png Screenshot from Atari 8-bit computer] |
|||
=={{header|AutoHotkey}}== |
|||
Requires [https://www.autohotkey.com/boards/viewtopic.php?t=6517 Gdip Library] |
|||
<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 |
|||
gdip1() |
|||
incr := 0 |
|||
π := 3.141592653589793 |
|||
loop |
|||
{ |
|||
incr := Mod(incr + 0.05, 360) |
|||
x1 := Width/2 |
|||
y1 := Height/2 |
|||
length := 5 |
|||
angle := incr |
|||
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, Width, Height, 0) |
|||
loop 150 |
|||
{ |
|||
x2 := x1 + length * Cos(angle * π/180) |
|||
y2 := y1 + length * Sin(angle * π/180) |
|||
Gdip_DrawLine(G, pPen, x1, y1, x2, y2) |
|||
x1 := x2 |
|||
y1 := y2 |
|||
length := length + 3 |
|||
angle := Mod(angle + incr, 360) |
|||
} |
|||
UpdateLayeredWindow(hwnd1, hdc, -1, -1, Width, Height) |
|||
Sleep 25 |
|||
} |
|||
return |
|||
;---------------------------------------------------------------- |
|||
Esc:: Pause, toggle |
|||
^Esc::ExitApp |
|||
;---------------------------------------------------------------- |
|||
gdip1(){ |
|||
global |
|||
Width := A_ScreenWidth+1, Height := A_ScreenHeight+1 |
|||
Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop |
|||
Gui, 1: Show, NA |
|||
hwnd1 := WinExist() |
|||
hbm := CreateDIBSection(Width, Height) |
|||
hdc := CreateCompatibleDC() |
|||
obm := SelectObject(hdc, hbm) |
|||
G := Gdip_GraphicsFromHDC(hdc) |
|||
Gdip_SetSmoothingMode(G, 4) |
|||
pBrush := Gdip_BrushCreateSolid("0xFF000000") |
|||
pPen := Gdip_CreatePen("0xFF00FF00", 1) |
|||
} |
|||
;---------------------------------------------------------------- |
|||
gdip2(){ |
|||
global |
|||
Gdip_DeletePen(pPen) |
|||
Gdip_DeleteBrush(pBrush) |
|||
SelectObject(hdc, obm) |
|||
DeleteObject(hbm) |
|||
DeleteDC(hdc) |
|||
Gdip_DeleteGraphics(G) |
|||
} |
|||
;---------------------------------------------------------------- |
|||
Exit: |
|||
gdip2() |
|||
Gdip_Shutdown(pToken) |
|||
ExitApp |
|||
Return |
|||
;----------------------------------------------------------------</syntaxhighlight> |
|||
=={{header|C}}== |
=={{header|C}}== |
||
Straightforward implementation of the pseudocode, incr and angle are integers and incr is incremented by 5 instead of 0.05 as the % operation in C is not defined for non-integers. Requires the [http://www.cs.colorado.edu/~main/bgi/cs1300/ WinBGIm] library. |
Straightforward implementation of the pseudocode, incr and angle are integers and incr is incremented by 5 instead of 0.05 as the % operation in C is not defined for non-integers. Requires the [http://www.cs.colorado.edu/~main/bgi/cs1300/ WinBGIm] library. |
||
<syntaxhighlight lang="c"> |
|||
<lang C> |
|||
#include<graphics.h> |
#include<graphics.h> |
||
#include<math.h> |
#include<math.h> |
||
Line 84: | Line 240: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Drawing; |
using System.Drawing; |
||
using System.Drawing.Drawing2D; |
using System.Drawing.Drawing2D; |
||
Line 150: | Line 306: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
This Windows programm has no animation, it will simply save 100 bitmaps onto your harddrive |
This Windows programm has no animation, it will simply save 100 bitmaps onto your harddrive |
||
< |
<syntaxhighlight lang="cpp"> |
||
#include <windows.h> |
#include <windows.h> |
||
#include <sstream> |
#include <sstream> |
||
Line 298: | Line 454: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Ceylon}}== |
=={{header|Ceylon}}== |
||
Be sure to import javafx.graphics and ceylon.numeric in your module.ceylon file. |
Be sure to import javafx.graphics and ceylon.numeric in your module.ceylon file. |
||
< |
<syntaxhighlight lang="ceylon">import javafx.application { |
||
Application |
Application |
||
} |
} |
||
Line 382: | Line 538: | ||
primaryStage.show(); |
primaryStage.show(); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Delphi}}== |
|||
{{works with|Delphi|6.0}} |
|||
{{libheader|SysUtils,StdCtrls}} |
|||
[[File:DelphiSpiralAnimaion.png|frame|none]] |
|||
<syntaxhighlight lang="Delphi"> |
|||
procedure PolySpiral(Image: TImage); |
|||
var Step,Angle,LineLen,I: integer; |
|||
var X,Y,X1,Y1: double; |
|||
begin |
|||
AbortFlag:=False; |
|||
ClearImage(Image,clBlack); |
|||
Image.Canvas.Pen.Width:=1; |
|||
while true do |
|||
begin |
|||
Image.Canvas.Pen.Color:=clYellow; |
|||
Step:=(Step + 5) mod 360; |
|||
X:=Image.Width/2; |
|||
Y:=Image.Height/2; |
|||
LineLen:=5; |
|||
angle:=Step; |
|||
for I:=1 to 150 do |
|||
begin |
|||
X1:=X + LineLen*cos(DegToRad(angle)); |
|||
Y1:=Y + LineLen*sin(DegToRad(angle)); |
|||
Image.Canvas.MoveTo(Round(X),Round(Y)); |
|||
Image.Canvas.LIneTo(Round(X1),Round(Y1)); |
|||
Image.Repaint; |
|||
LineLen:=LineLen+2; |
|||
Angle:=(Angle + Step) mod 360; |
|||
X:=X1; |
|||
Y:=Y1; |
|||
end; |
|||
if Application.Terminated then exit; |
|||
if AbortFlag then break; |
|||
Sleep(1200); |
|||
Application.ProcessMessages; |
|||
WaitForButton; |
|||
ClearImage(Image,clBlack); |
|||
end; |
|||
end; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
</pre> |
|||
=={{header|EasyLang}}== |
|||
[https://easylang.dev/show/#cod=bU/LCsMgELz7FXtMKwTzKvSQjxFjU8GskIQ2/n13jekDenLGmR1mTPBhhmvbCu/QPt2w3kGVjQgIGt2kVysAwHirZwYOzQw9FOmV5FTdCaYwQHNRrG8VqV2C8QO9xZFye6iYaRy9JcIZzKfwsHwYk3qjOo6tsAao9nsOrumPTBJMWHLEOQdnS2RLZMvi8L+FN3JUrI9YLrkdLFV+a7m1zLW/mhc7kGnCz/5SlOIF Run it] |
|||
<syntaxhighlight lang="easylang"> |
|||
color 944 |
|||
linewidth 0.3 |
|||
on animate |
|||
clear |
|||
incr = (incr + 0.05) mod 360 |
|||
x1 = 50 |
|||
y1 = 50 |
|||
length = 1 |
|||
angle = incr |
|||
move x1 y1 |
|||
for i = 1 to 150 |
|||
x2 = x1 + cos angle * length |
|||
y2 = y1 + sin angle * length |
|||
line x2 y2 |
|||
x1 = x2 |
|||
y1 = y2 |
|||
length += 1 |
|||
angle = (angle + incr) mod 360 |
|||
. |
|||
. |
|||
</syntaxhighlight> |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="freebasic">#include "fbgfx.bi" |
|||
#if __FB_LANG__ = "fb" |
|||
Using FB '' Scan code constants are stored in the FB namespace in lang FB |
|||
#endif |
|||
#define pi 4 * Atn(1) |
|||
#define Deg2Rad pi/180 |
|||
Dim As Integer w = 900, h = w |
|||
Screenres w, h, 8 |
|||
Windowtitle "Polyspiral" |
|||
Dim As Integer incr = 0, angulo, longitud, x1, y1, x2, y2, N |
|||
Do |
|||
incr += 1 |
|||
x1 = w / 2 |
|||
y1 = h / 2 |
|||
Pset (Fix(x1), Fix(y1)) |
|||
longitud = 5 |
|||
angulo = incr |
|||
For N = 1 To 150 |
|||
x2 = x1 + longitud * Cos(angulo * Deg2Rad) |
|||
y2 = y1 + longitud * Sin(angulo * Deg2Rad) |
|||
Line - (Fix(x2), Fix(y2)), N+16 |
|||
x1 = x2 |
|||
y1 = y2 |
|||
longitud += 3 |
|||
angulo += incr |
|||
Next N |
|||
Sleep 500 |
|||
Cls |
|||
Loop Until Multikey(SC_ESCAPE)</syntaxhighlight> |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
local fn DoIt |
|||
NSInteger i, t |
|||
double length, incr, x1, y1, x2, y2, twopi, angle, w, h |
|||
pen 2.0, fn ColorRed, NSLineCapStyleButt, NULL, 0 |
|||
incr = 0 : twopi = 2 * pi |
|||
w = 600 : h = 600 |
|||
t = 150 |
|||
while ( t > 0 ) |
|||
incr = ( incr + 0.05 mod twopi ) |
|||
x1 = w / 2 |
|||
y1 = h / 2 |
|||
length = 1.0 |
|||
angle = incr |
|||
line to x1, y1 |
|||
cls |
|||
for i = 1 to 300 |
|||
x2 = x1 + cos( angle ) * length |
|||
y2 = y1 + sin( angle ) * length |
|||
line to x1, y1 to x2, y2 |
|||
x1 = x2 : y1 = y2 |
|||
length = length + 1.0 |
|||
angle = ( angle + incr mod twopi ) |
|||
next |
|||
t-- |
|||
wend |
|||
end fn |
|||
window 1, @"Rosetta Code Polyspiral", fn CGRectMake( 0, 0, 600, 600 ) |
|||
WindowSetBackgroundColor( 1, fn ColorBlack ) |
|||
fn DoIt |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
[[File:Polyspiral FutureBasic.png]] |
|||
=={{header|Fōrmulæ}}== |
=={{header|Fōrmulæ}}== |
||
{{FormulaeEntry|page=https://formulae.org/?script=examples/Polyspiral}} |
|||
'''Solution''' |
|||
[[File:Fōrmulæ - Polyspiral 01.png]] |
|||
'''Test cases''' |
|||
[[File:Fōrmulæ - Polyspiral 02.png]] |
|||
[[File:Fōrmulæ - Polyspiral 03.png]] |
|||
[[File:Fōrmulæ - Polyspiral 04.png]] |
|||
[[File:Fōrmulæ - Polyspiral 05.png]] |
|||
[[File:Fōrmulæ - Polyspiral 06.png]] |
|||
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text ([http://wiki.formulae.org/Editing_F%C5%8Drmul%C3%A6_expressions more info]). Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for transportation effects more than visualization and edition. |
|||
[[File:Fōrmulæ - Polyspiral 07.png]] |
|||
The option to show Fōrmulæ programs and their results is showing images. Unfortunately images cannot be uploaded in Rosetta Code. |
|||
=={{header|Gnuplot}}== |
=={{header|Gnuplot}}== |
||
Line 397: | Line 728: | ||
===Plotting a polyspiral file-function for the load command=== |
===Plotting a polyspiral file-function for the load command=== |
||
'''plotpoly.gp''' file for the load command is the only possible imitation of the fine function in the '''gnuplot'''. |
'''plotpoly.gp''' file for the load command is the only possible imitation of the fine function in the '''gnuplot'''. |
||
< |
<syntaxhighlight lang="gnuplot"> |
||
## plotpoly.gp 1/10/17 aev |
## plotpoly.gp 1/10/17 aev |
||
## Plotting a polyspiral and writing to the png-file. |
## Plotting a polyspiral and writing to the png-file. |
||
Line 413: | Line 744: | ||
plot [0:c] t*cos(d*t), t*sin(d*t) lt rgb @clr |
plot [0:c] t*cos(d*t), t*sin(d*t) lt rgb @clr |
||
set output |
set output |
||
</ |
</syntaxhighlight> |
||
===Plotting many versions of a polyspiral.=== |
===Plotting many versions of a polyspiral.=== |
||
Line 424: | Line 755: | ||
[[File:PS6gp.png|right|thumb|Output PS6gp.png]] |
[[File:PS6gp.png|right|thumb|Output PS6gp.png]] |
||
< |
<syntaxhighlight lang="gnuplot"> |
||
## PSpirals.gp 1/10/17 aev |
## PSpirals.gp 1/10/17 aev |
||
## Plotting many polyspiral pictures. |
## Plotting many polyspiral pictures. |
||
Line 527: | Line 858: | ||
## Continue plotting starting with a range rng=110 to 400+ step 10 to discover new figures. |
## Continue plotting starting with a range rng=110 to 400+ step 10 to discover new figures. |
||
## END ## |
## END ## |
||
</ |
</syntaxhighlight> |
||
{{Output}} |
{{Output}} |
||
<pre> |
<pre> |
||
Line 536: | Line 867: | ||
===Plotting a polyspiral file-function for the load command (for animation)=== |
===Plotting a polyspiral file-function for the load command (for animation)=== |
||
'''plotpolya.gp''' file for the load command is the only possible imitation of the fine function in the '''gnuplot'''. |
'''plotpolya.gp''' file for the load command is the only possible imitation of the fine function in the '''gnuplot'''. |
||
< |
<syntaxhighlight lang="gnuplot"> |
||
## plotpolya.gp 1/19/17 aev |
## plotpolya.gp 1/19/17 aev |
||
## Plotting a polyspiral and writing to the png-file. Simple plot for animation. |
## Plotting a polyspiral and writing to the png-file. Simple plot for animation. |
||
Line 551: | Line 882: | ||
plot [0:c] t*cos(d*t), t*sin(d*t) lt rgb @clr |
plot [0:c] t*cos(d*t), t*sin(d*t) lt rgb @clr |
||
set output |
set output |
||
</ |
</syntaxhighlight> |
||
===Plotting many polyspiral and other pictures for animation.=== |
===Plotting many polyspiral and other pictures for animation.=== |
||
'''Note:''' No generated pictures here on RC. |
'''Note:''' No generated pictures here on RC. |
||
< |
<syntaxhighlight lang="gnuplot"> |
||
## PSpirals4a.gp 1/19/17 aev |
## PSpirals4a.gp 1/19/17 aev |
||
## Plotting many polyspiral and other pictures for animation |
## Plotting many polyspiral and other pictures for animation |
||
Line 611: | Line 942: | ||
##PS14 Not a polyspiral, but has many short secondary spirals. |
##PS14 Not a polyspiral, but has many short secondary spirals. |
||
rng=700; d=-1; clr = '"navy"'; filename = "PS14"; load "plotpolya.gp"; |
rng=700; d=-1; clr = '"navy"'; filename = "PS14"; load "plotpolya.gp"; |
||
</ |
</syntaxhighlight> |
||
{{Output}} |
{{Output}} |
||
<pre> |
<pre> |
||
Line 623: | Line 954: | ||
[[File:NiceFigsAnim.gif|right|thumb|Output NiceFigsAnim.gif]] |
[[File:NiceFigsAnim.gif|right|thumb|Output NiceFigsAnim.gif]] |
||
< |
<syntaxhighlight lang="gnuplot"> |
||
## Animation for polyspirals PS0 - PS6 |
## Animation for polyspirals PS0 - PS6 |
||
reset |
reset |
||
Line 645: | Line 976: | ||
do for [i=8:14]{plot 'PS'.i.'.png' binary filetype=png with rgbimage} |
do for [i=8:14]{plot 'PS'.i.'.png' binary filetype=png with rgbimage} |
||
set output |
set output |
||
</ |
</syntaxhighlight> |
||
{{Output}} |
{{Output}} |
||
<pre> |
<pre> |
||
Line 653: | Line 984: | ||
===Showing 2 animated gif-files.=== |
===Showing 2 animated gif-files.=== |
||
Create 2 the following html-files and envoke them in browser. |
Create 2 the following html-files and envoke them in browser. |
||
< |
<syntaxhighlight lang="html"> |
||
<!-- PolySpirsAnim.html --> |
<!-- PolySpirsAnim.html --> |
||
<html><body> |
<html><body> |
||
Line 660: | Line 991: | ||
<img src="PolySpirsAnim.gif"> |
<img src="PolySpirsAnim.gif"> |
||
</body></html> |
</body></html> |
||
</ |
</syntaxhighlight> |
||
< |
<syntaxhighlight lang="html"> |
||
<!-- NiceFigsAnim.html --> |
<!-- NiceFigsAnim.html --> |
||
<html><body> |
<html><body> |
||
Line 668: | Line 999: | ||
<img src="NiceFigsAnim.gif"> |
<img src="NiceFigsAnim.gif"> |
||
</body></html> |
</body></html> |
||
</ |
</syntaxhighlight> |
||
{{Output}} |
{{Output}} |
||
<pre> |
<pre> |
||
Line 684: | Line 1,015: | ||
$ eog polyspiral2.gif |
$ eog polyspiral2.gif |
||
</pre> |
</pre> |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 796: | Line 1,127: | ||
log.Fatal(err2) |
log.Fatal(err2) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
Line 803: | Line 1,134: | ||
This implementation compiles to javascript that runs in the browser using the [https://github.com/ghcjs/ghcjs ghcjs compiler ] . The [https://github.com/reflex-frp/reflex-dom reflex-dom ] library is used to help with svg rendering and animation. |
This implementation compiles to javascript that runs in the browser using the [https://github.com/ghcjs/ghcjs ghcjs compiler ] . The [https://github.com/reflex-frp/reflex-dom reflex-dom ] library is used to help with svg rendering and animation. |
||
< |
<syntaxhighlight lang="haskell">{-# LANGUAGE OverloadedStrings #-} |
||
import Reflex |
import Reflex |
||
import Reflex.Dom |
import Reflex.Dom |
||
Line 885: | Line 1,216: | ||
elSvgns t m ma = do |
elSvgns t m ma = do |
||
(el, val) <- elDynAttrNS' (Just "http://www.w3.org/2000/svg") t m ma |
(el, val) <- elDynAttrNS' (Just "http://www.w3.org/2000/svg") t m ma |
||
return val</ |
return val</syntaxhighlight> |
||
Link to live demo: https://dc25.github.io/rosettaCode__Polyspiral_haskell/ |
Link to live demo: https://dc25.github.io/rosettaCode__Polyspiral_haskell/ |
||
=={{header|IS-BASIC}}== |
=={{header|IS-BASIC}}== |
||
< |
<syntaxhighlight lang="is-basic">100 PROGRAM "PolySp.bas" |
||
110 OPTION ANGLE DEGREES |
110 OPTION ANGLE DEGREES |
||
120 LET CH=2 |
120 LET CH=2 |
||
Line 914: | Line 1,245: | ||
320 LET D=740 |
320 LET D=740 |
||
330 CONTINUE |
330 CONTINUE |
||
340 END HANDLER</ |
340 END HANDLER</syntaxhighlight> |
||
=={{header|J}}== |
=={{header|J}}== |
||
Line 920: | Line 1,251: | ||
{{trans|java}} |
{{trans|java}} |
||
< |
<syntaxhighlight lang="j">require 'gl2 trig media/imagekit' |
||
coinsert 'jgl2' |
coinsert 'jgl2' |
||
Line 969: | Line 1,300: | ||
) |
) |
||
poly_run''</ |
poly_run''</syntaxhighlight> |
||
Note that we're using a lot of [[j:Guides/Window_Driver/Command_Reference|wd]] commands here. You'll need to be running [[j:System/Installation|jqt]] for this to work. |
Note that we're using a lot of [[j:Guides/Window_Driver/Command_Reference|wd]] commands here. You'll need to be running [[j:System/Installation|jqt]] for this to work. |
||
Line 976: | Line 1,307: | ||
[[File:Polyspiral_java2.png|300px|thumb|right]] |
[[File:Polyspiral_java2.png|300px|thumb|right]] |
||
{{works with|Java|8}} |
{{works with|Java|8}} |
||
< |
<syntaxhighlight lang="java">import java.awt.*; |
||
import java.awt.event.ActionEvent; |
import java.awt.event.ActionEvent; |
||
import javax.swing.*; |
import javax.swing.*; |
||
Line 1,037: | Line 1,368: | ||
}); |
}); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
Line 1,048: | Line 1,379: | ||
* An image uploading is still blocked. But you have a browser!? So, copy/paste/save this page and double click it. |
* An image uploading is still blocked. But you have a browser!? So, copy/paste/save this page and double click it. |
||
{{Works with|Chrome}} (or any other browser supporting Canvas tag) |
{{Works with|Chrome}} (or any other browser supporting Canvas tag) |
||
< |
<syntaxhighlight lang="html"> |
||
<!-- Polyspiral.html --> |
<!-- Polyspiral.html --> |
||
<html> |
<html> |
||
Line 1,109: | Line 1,440: | ||
</body> |
</body> |
||
</html> |
</html> |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Output}} |
{{Output}} |
||
<pre> |
<pre> |
||
Line 1,119: | Line 1,450: | ||
===Version #2 - Animated=== |
===Version #2 - Animated=== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="javascript"><!DOCTYPE html> |
||
<html lang="en"> |
<html lang="en"> |
||
<head> |
<head> |
||
Line 1,200: | Line 1,531: | ||
</body> |
</body> |
||
</html></ |
</html></syntaxhighlight> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia">using Gtk, Graphics, Colors |
||
const can = @GtkCanvas() |
const can = @GtkCanvas() |
||
Line 1,263: | Line 1,594: | ||
sleep(0.5) |
sleep(0.5) |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="scala">// version 1.1.0 |
||
import java.awt.* |
import java.awt.* |
||
Line 1,321: | Line 1,652: | ||
f.setVisible(true) |
f.setVisible(true) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
{{libheader|LÖVE}} |
{{libheader|LÖVE}} |
||
LÖVE defaults to animating at sixty frames per second, so the patterns become very complex very quickly. |
LÖVE defaults to animating at sixty frames per second, so the patterns become very complex very quickly. |
||
< |
<syntaxhighlight lang="lua">function love.load () |
||
love.window.setTitle("Polyspiral") |
love.window.setTitle("Polyspiral") |
||
incr = 0 |
incr = 0 |
||
Line 1,348: | Line 1,679: | ||
angle = (angle + incr) % 360 |
angle = (angle + incr) % 360 |
||
end |
end |
||
end</ |
end</syntaxhighlight> |
||
[[File:love2dPolyspiral.jpg]] |
[[File:love2dPolyspiral.jpg]] |
||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
|||
<syntaxhighlight lang="mathematica">linedata = {}; |
|||
Dynamic[Graphics[Line[linedata], PlotRange -> 1000]] |
|||
Do[ |
|||
linedata = AnglePath[{#, \[Theta]} & /@ Range[5, 300, 3]]; |
|||
Pause[0.1]; |
|||
, |
|||
{\[Theta], Subdivide[0.1, 1, 100]} |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
Outputs an animating graphic with a spiral with changing angle. |
|||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
Line 1,355: | Line 1,698: | ||
As Julia, we use Gtk/Cairo to draw the polyspirals. So, the drawing part is taken, with some modifications, from Julia solution. |
As Julia, we use Gtk/Cairo to draw the polyspirals. So, the drawing part is taken, with some modifications, from Julia solution. |
||
< |
<syntaxhighlight lang="nim"># Pendulum simulation. |
||
import math, random |
import math, random |
||
Line 1,467: | Line 1,810: | ||
let app = newApplication(Application, "Rosetta.polyspiral") |
let app = newApplication(Application, "Rosetta.polyspiral") |
||
discard app.connect("activate", activate) |
discard app.connect("activate", activate) |
||
discard app.run()</ |
discard app.run()</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Line 1,477: | Line 1,820: | ||
You can find a few others on [http://oeis.org/wiki/User:Anatoly_E._Voevudko/VoeLib.gp#Plotting_helper_functions OEIS Wiki] and here on RC Wiki. |
You can find a few others on [http://oeis.org/wiki/User:Anatoly_E._Voevudko/VoeLib.gp#Plotting_helper_functions OEIS Wiki] and here on RC Wiki. |
||
< |
<syntaxhighlight lang="parigp"> |
||
\\ Plot the line from x1,y1 to x2,y2. |
\\ Plot the line from x1,y1 to x2,y2. |
||
plotline(x1,y1,x2,y2,w=0)={plotmove(w, x1,y1);plotrline(w,x2-x1,y2-y1);} |
plotline(x1,y1,x2,y2,w=0)={plotmove(w, x1,y1);plotrline(w,x2-x1,y2-y1);} |
||
Line 1,485: | Line 1,828: | ||
cartes2(r,a,rndf=0)={my(v,x,y); x=r*cos(a); y=r*sin(a); |
cartes2(r,a,rndf=0)={my(v,x,y); x=r*cos(a); y=r*sin(a); |
||
if(rndf==0, return([x,y]), return(round([x,y])))} |
if(rndf==0, return([x,y]), return(round([x,y])))} |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Version #1. Polyspiral (a spiral made of multiple line segments).=== |
===Version #1. Polyspiral (a spiral made of multiple line segments).=== |
||
Line 1,498: | Line 1,841: | ||
[[File:Polyspiral4.png|100px|right|thumb|Output Polyspiral4.png]] |
[[File:Polyspiral4.png|100px|right|thumb|Output Polyspiral4.png]] |
||
< |
<syntaxhighlight lang="parigp"> |
||
\\Polyspiral (a spiral made of multiple line segments) |
\\Polyspiral (a spiral made of multiple line segments) |
||
\\ 4/15/16 aev |
\\ 4/15/16 aev |
||
Line 1,533: | Line 1,876: | ||
polyspiral(100000,100000,0.03,3,2);\\Polyspiral4.png |
polyspiral(100000,100000,0.03,3,2);\\Polyspiral4.png |
||
} |
} |
||
</ |
</syntaxhighlight> |
||
{{Output}} |
{{Output}} |
||
Line 1,565: | Line 1,908: | ||
[[File:Spiralz1.png|100px|right|thumb|Output Spiralz.png]] |
[[File:Spiralz1.png|100px|right|thumb|Output Spiralz.png]] |
||
< |
<syntaxhighlight lang="parigp"> |
||
\\ plotpspiralz() Multi-spiral figure translated from zkl using my own ploting functions. |
\\ plotpspiralz() Multi-spiral figure translated from zkl using my own ploting functions. |
||
\\ 4/15/16 aev |
\\ 4/15/16 aev |
||
Line 1,602: | Line 1,945: | ||
Spiralz(640,2,3.0,3.0,128); \\Spiralz1.png |
Spiralz(640,2,3.0,3.0,128); \\Spiralz1.png |
||
} |
} |
||
</ |
</syntaxhighlight> |
||
{{Output}} |
{{Output}} |
||
Line 1,614: | Line 1,957: | ||
Click Start button to run, then runs continuously. |
Click Start button to run, then runs continuously. |
||
It takes just a little over four minutes to complete a full 360 degree cycle. |
It takes just a little over four minutes to complete a full 360 degree cycle. |
||
< |
<syntaxhighlight lang="perl"> |
||
#!/usr/bin/perl |
#!/usr/bin/perl |
||
Line 1,662: | Line 2,005: | ||
$c->createLine( @pts ); |
$c->createLine( @pts ); |
||
$mw->after($wait => \&step); |
$mw->after($wait => \&step); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 1,668: | Line 2,011: | ||
'M' toggles "mod360", which inverts the angle every 360/2PI or so, since sin/cos |
'M' toggles "mod360", which inverts the angle every 360/2PI or so, since sin/cos |
||
accept arguments in radians not degrees (and mod 2*PI changes nothing), producing |
accept arguments in radians not degrees (and mod 2*PI changes nothing), producing |
||
non-true polyspirals, but quite interesting nevertheless. |
non-true polyspirals, but quite interesting nevertheless. |
||
You can run this online [http://phix.x10.mx/p2js/Polyspiral.htm here]. |
|||
{{libheader|Phix/pGUI}} |
{{libheader|Phix/pGUI}} |
||
{{libheader|Phix/online}} |
|||
<lang Phix>-- demo\rosetta\Polyspiral.exw |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
include pGUI.e |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
-- demo\rosetta\Polyspiral.exw |
|||
-- =========================== |
|||
-- |
|||
-- Space toggles the timer, '+' increases speed (up to 100 FPS), '-' decreases speed |
|||
-- 'M' toggles "mod360", which inverts the angle every 360/2PI or so, since sin/cos |
|||
-- accept arguments in radians not degrees (and mod 2*PI changes nothing), producing |
|||
-- non-true polyspirals, but quite interesting nevertheless. |
|||
--</span> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">TITLE</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Polyspiral"</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: #0000FF;">,</span> <span style="color: #000000;">timer</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: #004080;">atom</span> <span style="color: #000000;">incr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
<span style="color: #004080;">bool</span> <span style="color: #000000;">mod360</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Polyspiral</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y1</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">angle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">incr</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5</span> |
|||
<span style="color: #000000;">incr</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">0.05</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">mod360</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">incr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">incr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">360</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">150</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">x2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x1</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">angle</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">len</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">y2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y1</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">angle</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">len</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: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">#200</span><span style="color: #0000FF;">+</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">#40</span><span style="color: #0000FF;">+</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">#10</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">cdCanvasLine</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y2</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y1</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y2</span><span style="color: #0000FF;">}</span> |
|||
<span style="color: #000000;">len</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">3</span> |
|||
<span style="color: #000000;">angle</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">incr</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">mod360</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">angle</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">angle</span><span style="color: #0000FF;">,</span><span style="color: #000000;">360</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;">for</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</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: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">cdCanvasClear</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">Polyspiral</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;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</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: #004080;">integer</span> <span style="color: #000000;">ms</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TIME"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"%s (timer=%d [%g FPS], angle %3.2f%s)"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">TITLE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ms</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">/</span><span style="color: #000000;">ms</span><span style="color: #0000FF;">,</span><span style="color: #000000;">incr</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mod360</span><span style="color: #0000FF;">?</span><span style="color: #008000;">" (mod360)"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">""</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;">timer_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*timer*/</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">IupUpdate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_IGNORE</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;">canvas</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;">canvas</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_GRAY</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;">key_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;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_ESC</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RUN"</span><span style="color: #0000FF;">,</span><span style="color: #008080;">not</span> <span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RUN"</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"+-"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RUN"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-(</span><span style="color: #008000;">','</span><span style="color: #0000FF;">-</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ('+' ==> +1, '-' ==> -1)</span> |
|||
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TIME"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">IupGetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TIME"</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">timer</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RUN"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)=</span><span style="color: #008000;">'M'</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">mod360</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">not</span> <span style="color: #000000;">mod360</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CONTINUE</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</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=640x640"</span><span style="color: #0000FF;">)</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;">timer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupTimer</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"timer_cb"</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">20</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="%s"`</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">TITLE</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"KEY_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"key_cb"</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: #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> |
|||
<!--</syntaxhighlight>--> |
|||
=={{header|Processing}}== |
|||
Ihandle dlg, canvas, timer |
|||
{{trans|C}} |
|||
cdCanvas cddbuffer, cdcanvas |
|||
<syntaxhighlight lang="java"> |
|||
//Aamrun, 2nd July 2022 |
|||
int incr = 0, angle, i, length; |
|||
constant TITLE = "Polyspiral" |
|||
float x,y,x1,y1; |
|||
double factor = PI/180; |
|||
void setup() { |
|||
atom incr = 0 |
|||
size(1000, 1000); |
|||
bool mod360 = false |
|||
stroke(255); |
|||
} |
|||
procedure Polyspiral(atom x1, y1) |
|||
atom angle = incr |
|||
integer len = 5 |
|||
incr += 0.05 |
|||
if mod360 then |
|||
incr = mod(incr,360) |
|||
end if |
|||
for i=1 to 150 do |
|||
atom x2 = x1 + cos(angle)*len |
|||
atom y2 = y1 + sin(angle)*len |
|||
cdCanvasSetForeground(cddbuffer, i*#200+i*#40+i*#10) |
|||
cdCanvasLine(cddbuffer, x1, y1, x2, y2) |
|||
{x1, y1} = {x2, y2} |
|||
len += 3 |
|||
angle += incr |
|||
if mod360 then |
|||
angle = mod(angle,360) |
|||
end if |
|||
end for |
|||
end procedure |
|||
void draw() { |
|||
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/) |
|||
background(51); |
|||
integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE") |
|||
incr = (incr + 5)%360; |
|||
cdCanvasActivate(cddbuffer) |
|||
cdCanvasClear(cddbuffer) |
|||
x = width/2; |
|||
y = height/2; |
|||
cdCanvasFlush(cddbuffer) |
|||
integer ms = IupGetInt(timer,"TIME") |
|||
length = 5; |
|||
IupSetStrAttribute(dlg, "TITLE", "%s (timer=%d [%g FPS], angle %3.2f%s)", |
|||
angle = incr; |
|||
{TITLE,ms,1000/ms,incr,iff(mod360?" (mod360)":"")}) |
|||
return IUP_DEFAULT |
|||
for(i=1;i<=150;i++){ |
|||
end function |
|||
x1 = x + (float)(length*Math.cos(factor*angle)); |
|||
y1 = y + (float)(length*Math.sin(factor*angle)); |
|||
function timer_cb(Ihandle /*ih*/) |
|||
line(x,y,x1,y1); |
|||
return IUP_IGNORE |
|||
length += 3; |
|||
end function |
|||
angle = (angle + incr)%360; |
|||
function map_cb(Ihandle ih) |
|||
cdcanvas = cdCreateCanvas(CD_IUP, ih) |
|||
x = x1; |
|||
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas) |
|||
y = y1; |
|||
cdCanvasSetBackground(cddbuffer, CD_WHITE) |
|||
} |
|||
cdCanvasSetForeground(cddbuffer, CD_GRAY) |
|||
} |
|||
return IUP_DEFAULT |
|||
</syntaxhighlight> |
|||
end function |
|||
function esc_close(Ihandle /*ih*/, atom c) |
|||
if c=K_ESC then return IUP_CLOSE end if |
|||
if c=' ' then |
|||
IupSetInt(timer,"RUN",not IupGetInt(timer,"RUN")) |
|||
elsif find(c,"+-") then |
|||
-- ('+' increases speed, by decreasing TIME) |
|||
IupSetInt(timer,"TIME",max(10,IupGetInt(timer,"TIME")-(','-c)*10)) |
|||
IupSetInt(timer,"RUN",0) |
|||
IupSetInt(timer,"RUN",1) |
|||
elsif upper(c)='M' then |
|||
mod360 = not mod360 |
|||
end if |
|||
return IUP_CONTINUE |
|||
end function |
|||
procedure main() |
|||
IupOpen() |
|||
canvas = IupCanvas(NULL) |
|||
IupSetAttribute(canvas, "RASTERSIZE", "640x640") |
|||
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb")) |
|||
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb")) |
|||
timer = IupTimer(Icallback("timer_cb"), 20) |
|||
dlg = IupDialog(canvas) |
|||
IupSetAttribute(dlg, "TITLE", TITLE) |
|||
IupSetCallback(dlg, "K_ANY", Icallback("esc_close")) |
|||
IupShow(dlg) |
|||
IupSetAttribute(canvas, "RASTERSIZE", NULL) |
|||
IupMainLoop() |
|||
IupClose() |
|||
end procedure |
|||
main()</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{libheader|Pygame}} |
{{libheader|Pygame}} |
||
< |
<syntaxhighlight lang="python">import math |
||
import pygame |
import pygame |
||
Line 1,805: | Line 2,192: | ||
pygame.display.flip() |
pygame.display.flip() |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Quackery}}== |
|||
<syntaxhighlight lang="Quackery"> [ $ "turtleduck.qky" loadfile ] now! |
|||
[ 1000 * time + |
|||
[ dup time < until ] |
|||
drop ] is ms ( n --> ) |
|||
[ turtle 0 frames |
|||
3601 times |
|||
[ clear |
|||
i^ 3600 |
|||
1000 times |
|||
[ i^ 1+ 1 walk |
|||
2dup turn ] |
|||
2drop |
|||
frame |
|||
10 ms ] ] is polyspiral ( --> )</syntaxhighlight> |
|||
{{out}} |
|||
https://youtu.be/qZemJJBUekM |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Uses the *universe* animation |
Uses the *universe* animation |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(require 2htdp/universe pict racket/draw) |
(require 2htdp/universe pict racket/draw) |
||
Line 1,834: | Line 2,245: | ||
width height))) |
width height))) |
||
(animate (polyspiral 400 400 2 1000))</ |
(animate (polyspiral 400 400 2 1000))</syntaxhighlight> |
||
See the output for yourself! |
See the output for yourself! |
||
Line 1,845: | Line 2,256: | ||
Sort of an ersatz animation. Write updates to a svg file, most modern viewers will update as the content changes. |
Sort of an ersatz animation. Write updates to a svg file, most modern viewers will update as the content changes. |
||
<lang |
<syntaxhighlight lang="raku" line>use SVG; |
||
my $w = 600; |
my $w = 600; |
||
my $h = 600; |
my $h = 600; |
||
Line 1,888: | Line 2,299: | ||
} |
} |
||
( $r, $g, $b ).map: ((*+$m) * 255).Int |
( $r, $g, $b ).map: ((*+$m) * 255).Int |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
See [https://github.com/thundergnat/rc/blob/master/img/polyspiral-perl6.gif polyspiral-perl6.gif] (offsite animated gif image) |
See [https://github.com/thundergnat/rc/blob/master/img/polyspiral-perl6.gif polyspiral-perl6.gif] (offsite animated gif image) |
||
Line 1,895: | Line 2,306: | ||
Uses the same basic algorithm but fully animated. Use the up / down arrow keys to speed up / slow down the update speed. Use PgUp / PgDn keys to increment / decrement animation speed by large amounts. Use left / right arrow keys to reverse the "direction" of angle change. Press Space bar to toggle animation / reset to minimum speed. Left Control key to toggle stationary / rotating center. Use + / - keys to add remove line segments. |
Uses the same basic algorithm but fully animated. Use the up / down arrow keys to speed up / slow down the update speed. Use PgUp / PgDn keys to increment / decrement animation speed by large amounts. Use left / right arrow keys to reverse the "direction" of angle change. Press Space bar to toggle animation / reset to minimum speed. Left Control key to toggle stationary / rotating center. Use + / - keys to add remove line segments. |
||
<lang |
<syntaxhighlight lang="raku" line>use SDL2::Raw; |
||
my $width = 900; |
my $width = 900; |
||
Line 2,007: | Line 2,418: | ||
} |
} |
||
( $r, $g, $b ).map: ((*+$m) * 255).Int |
( $r, $g, $b ).map: ((*+$m) * 255).Int |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
# Project : Polyspiral |
# Project : Polyspiral |
||
Line 2,066: | Line 2,477: | ||
} |
} |
||
label1 { setpicture(p1) show() } |
label1 { setpicture(p1) show() } |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
Line 2,073: | Line 2,484: | ||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
===Java Swing Interoperability=== |
===Java Swing Interoperability=== |
||
< |
<syntaxhighlight lang="scala">import java.awt._ |
||
import java.awt.event.ActionEvent |
import java.awt.event.ActionEvent |
||
Line 2,127: | Line 2,538: | ||
) |
) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|SPL}}== |
=={{header|SPL}}== |
||
< |
<syntaxhighlight lang="spl">width,height = #.scrsize() |
||
#.angle(#.degrees) |
#.angle(#.degrees) |
||
#.scroff() |
#.scroff() |
||
Line 2,151: | Line 2,562: | ||
< |
< |
||
#.scr() |
#.scr() |
||
<</ |
<</syntaxhighlight> |
||
=={{header|SVG}}== |
=={{header|SVG}}== |
||
Line 2,161: | Line 2,572: | ||
It requires building up layers, animated over a rotation transformation. This is verbose, so the code below has been truncated, and the [https://codepen.io/shephero/full/xxbaWXb demo] uses another language ([https://codepen.io/shephero/full/xxbaWXb Pug]) to generate the source. |
It requires building up layers, animated over a rotation transformation. This is verbose, so the code below has been truncated, and the [https://codepen.io/shephero/full/xxbaWXb demo] uses another language ([https://codepen.io/shephero/full/xxbaWXb Pug]) to generate the source. |
||
< |
<syntaxhighlight lang="html"> |
||
<svg viewBox="0 0 100 100" stroke="#000" stroke-width="0.3"> |
<svg viewBox="0 0 100 100" stroke="#000" stroke-width="0.3"> |
||
<g> |
<g> |
||
Line 2,179: | Line 2,590: | ||
</g> |
</g> |
||
</svg> |
</svg> |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Wren}}== |
|||
{{trans|Kotlin}} |
|||
{{libheader|DOME}} |
|||
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color |
|||
import "dome" for Window |
|||
import "math" for Math |
|||
var Radians = Fn.new { |d| d * Num.pi / 180 } |
|||
class Polyspiral { |
|||
construct new(width, height) { |
|||
Window.title = "Polyspiral" |
|||
Window.resize(width, height) |
|||
Canvas.resize(width, height) |
|||
_w = width |
|||
_h = height |
|||
_inc = 0 |
|||
} |
|||
init() { |
|||
drawSpiral(5, Radians.call(_inc)) |
|||
} |
|||
drawSpiral(length, angleIncrement) { |
|||
Canvas.cls(Color.white) |
|||
var x1 = _w / 2 |
|||
var y1 = _h / 2 |
|||
var len = length |
|||
var angle = angleIncrement |
|||
for (i in 0...150) { |
|||
var col = Color.hsv(i / 150 * 360, 1, 1) |
|||
var x2 = x1 + Math.cos(angle) * len |
|||
var y2 = y1 - Math.sin(angle) * len |
|||
Canvas.line(x1.truncate, y1.truncate, x2.truncate, y2.truncate, col) |
|||
x1 = x2 |
|||
y1 = y2 |
|||
len = len + 3 |
|||
angle = (angle + angleIncrement) % (Num.pi * 2) |
|||
} |
|||
} |
|||
update() { |
|||
_inc = (_inc + 0.05) % 360 |
|||
} |
|||
draw(alpha) { |
|||
drawSpiral(5, Radians.call(_inc)) |
|||
} |
|||
} |
|||
var Game = Polyspiral.new(640, 640)</syntaxhighlight> |
|||
=={{header|XPL0}}== |
|||
There is no need for the MOD operator shown in the pseudo code for XPL0's |
|||
trig functions because they handle argument angles outside 0 to 360 |
|||
degrees (2 Pi radians). |
|||
<syntaxhighlight lang="xpl0"> |
|||
def Width=640., Height=480.; |
|||
def Deg2Rad = 3.141592654/180.; |
|||
real Incr, Angle, Length, X, Y, X1, Y1; |
|||
int N; |
|||
[SetVid($101); \VESA 640x480x8 graphics |
|||
Incr:= 0.; |
|||
repeat Incr:= Incr+1.; |
|||
X:= Width/2.; Y:= Height/2.; |
|||
Move(fix(X), fix(Y)); |
|||
Length:= 5.; |
|||
Angle:= Incr; |
|||
for N:= 1 to 150 do |
|||
[X1:= X + Length*Cos(Angle*Deg2Rad); |
|||
Y1:= Y + Length*Sin(Angle*Deg2Rad); |
|||
Line(fix(X1), fix(Y1), N+16); |
|||
X:= X1; Y:= Y1; |
|||
Length:= Length+3.; |
|||
Angle:= Angle+Incr; |
|||
]; |
|||
DelayUS(83_333); |
|||
Clear; |
|||
until KeyHit; |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
https://www.youtube.com/watch?v=p1M2VVY3abM |
|||
The actual program looks better and runs under MS-DOS, Windows (with EXPL) and RPi. |
|||
</pre> |
|||
=={{header|Yabasic}}== |
=={{header|Yabasic}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="yabasic">w = 1024 : h = 600 |
||
open window w, h |
open window w, h |
||
color 255,0,0 |
color 255,0,0 |
||
Line 2,207: | Line 2,706: | ||
next |
next |
||
pause 1 |
pause 1 |
||
end while</ |
end while</syntaxhighlight> |
||
=={{header|Zig}}== |
|||
{{works with|Zig|0.11.0}} {{works with|raylib|4.6-dev}} |
|||
{{libheader|raylib}} |
|||
<syntaxhighlight lang="zig"> |
|||
const std = @import("std"); |
|||
const rl = @cImport({ |
|||
@cInclude("raylib.h"); |
|||
@cInclude("raymath.h"); |
|||
}); |
|||
const SCREEN_WIDTH = 640; |
|||
const SCREEN_HEIGHT = 480; |
|||
var incr: f32 = 0; |
|||
pub fn main() void { |
|||
rl.SetConfigFlags(rl.FLAG_WINDOW_RESIZABLE | rl.FLAG_VSYNC_HINT); |
|||
rl.SetTargetFPS(60); |
|||
rl.InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Polyspiral"); |
|||
while (!rl.WindowShouldClose()) |
|||
updateDrawFrame(); |
|||
rl.CloseWindow(); |
|||
} |
|||
fn updateDrawFrame() void { |
|||
rl.BeginDrawing(); |
|||
rl.ClearBackground(rl.BLACK); |
|||
incr = @mod(incr + 0.001, 360); |
|||
drawSpiral(5, std.math.degreesToRadians(f32, incr)); |
|||
rl.EndDrawing(); |
|||
} |
|||
fn drawSpiral(_length: f32, _angle: f32) void { |
|||
const width = rl.GetScreenWidth(); |
|||
const height = rl.GetScreenHeight(); |
|||
var point0 = rl.Vector2{ .x = @as(f32, @floatFromInt(width)) / 2, .y = @as(f32, @floatFromInt(height)) / 2 }; |
|||
var length = _length; |
|||
var angle = _angle; |
|||
for (0..150) |_| { |
|||
const line_vector = rl.Vector2Rotate(rl.Vector2{ .x = length, .y = 0 }, angle); |
|||
const point1 = rl.Vector2Add(point0, line_vector); |
|||
rl.DrawLineV(point0, point1, rl.LIME); |
|||
point0 = point1; |
|||
length += 3; |
|||
angle += incr; |
|||
angle = @mod(angle, comptime @as(f32, (2.0 * std.math.pi))); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
Line 2,214: | Line 2,769: | ||
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">w,h:=640,640; |
||
bitmap:=PPM(w,h,0xFF|FF|FF); // White background |
bitmap:=PPM(w,h,0xFF|FF|FF); // White background |
||
angleIncrement:=(3.0).toRad(); |
angleIncrement:=(3.0).toRad(); |
||
Line 2,232: | Line 2,787: | ||
angleIncrement=(angleIncrement + 0.05); |
angleIncrement=(angleIncrement + 0.05); |
||
Atomic.sleep(3); |
Atomic.sleep(3); |
||
}</ |
}</syntaxhighlight> |
Latest revision as of 16:39, 25 January 2024
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
A Polyspiral is a spiral made of multiple line segments, whereby each segment is larger (or smaller) than the previous one by a given amount. Each segment also changes direction at a given angle.
- Task
Animate a series of polyspirals, by drawing a complete spiral then incrementing the angle, and (after clearing the background) drawing the next, and so on. Every spiral will be a frame of the animation. The animation may stop as it goes full circle or continue indefinitely. The given input values may be varied.
If animation is not practical in your programming environment, you may show a single frame instead.
- Pseudo code
set incr to 0.0 // animation loop WHILE true incr = (incr + 0.05) MOD 360 x = width / 2 y = height / 2 length = 5 angle = incr // spiral loop FOR 1 TO 150 drawline change direction by angle length = length + 3 angle = (angle + incr) MOD 360 ENDFOR
Action!
INCLUDE "H6:REALMATH.ACT"
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 i,angle,x,y,tmp
REAL rx,ry,len,dlen,r1,r2,r3,r256
IntToReal(x0,rx)
IntToReal(y0,ry)
ValR("1.9",len)
ValR("1.14",dlen)
IntToReal(256,r256)
angle=0
Plot(x0,y0)
FOR i=1 TO 150
DO
tmp=Cos(angle)
IntToRealForNeg(tmp,r1)
RealDiv(r1,r256,r2)
RealMult(r2,len,r1)
RealAdd(rx,r1,r2)
RealAssign(r2,rx)
tmp=Sin(angle)
IntToRealForNeg(tmp,r1)
RealDiv(r1,r256,r2)
RealMult(r2,len,r1)
RealAdd(ry,r1,r2)
RealAssign(r2,ry)
x=RealToInt(rx)
y=RealToInt(ry)
DrawTo(x,y)
RealAdd(len,dlen,r1)
RealAssign(r1,len)
angle==+123
IF angle>360 THEN
angle==-360
FI
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
AutoHotkey
Requires Gdip Library
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
OnExit, Exit
gdip1()
incr := 0
π := 3.141592653589793
loop
{
incr := Mod(incr + 0.05, 360)
x1 := Width/2
y1 := Height/2
length := 5
angle := incr
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, Width, Height, 0)
loop 150
{
x2 := x1 + length * Cos(angle * π/180)
y2 := y1 + length * Sin(angle * π/180)
Gdip_DrawLine(G, pPen, x1, y1, x2, y2)
x1 := x2
y1 := y2
length := length + 3
angle := Mod(angle + incr, 360)
}
UpdateLayeredWindow(hwnd1, hdc, -1, -1, Width, Height)
Sleep 25
}
return
;----------------------------------------------------------------
Esc:: Pause, toggle
^Esc::ExitApp
;----------------------------------------------------------------
gdip1(){
global
Width := A_ScreenWidth+1, Height := A_ScreenHeight+1
Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop
Gui, 1: Show, NA
hwnd1 := WinExist()
hbm := CreateDIBSection(Width, Height)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetSmoothingMode(G, 4)
pBrush := Gdip_BrushCreateSolid("0xFF000000")
pPen := Gdip_CreatePen("0xFF00FF00", 1)
}
;----------------------------------------------------------------
gdip2(){
global
Gdip_DeletePen(pPen)
Gdip_DeleteBrush(pBrush)
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)
}
;----------------------------------------------------------------
Exit:
gdip2()
Gdip_Shutdown(pToken)
ExitApp
Return
;----------------------------------------------------------------
C
Straightforward implementation of the pseudocode, incr and angle are integers and incr is incremented by 5 instead of 0.05 as the % operation in C is not defined for non-integers. Requires the WinBGIm library.
#include<graphics.h>
#include<math.h>
#define factor M_PI/180
#define LAG 1000
void polySpiral(int windowWidth,int windowHeight){
int incr = 0, angle, i, length;
double x,y,x1,y1;
while(1){
incr = (incr + 5)%360;
x = windowWidth/2;
y = windowHeight/2;
length = 5;
angle = incr;
for(i=1;i<=150;i++){
x1 = x + length*cos(factor*angle);
y1 = y + length*sin(factor*angle);
line(x,y,x1,y1);
length += 3;
angle = (angle + incr)%360;
x = x1;
y = y1;
}
delay(LAG);
cleardevice();
}
}
int main()
{
initwindow(500,500,"Polyspiral");
polySpiral(500,500);
closegraph();
return 0;
}
C#
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Windows.Threading;
namespace Polyspiral
{
public partial class Form1 : Form
{
private double inc;
public Form1()
{
Width = Height = 640;
StartPosition = FormStartPosition.CenterScreen;
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer,
true);
var timer = new DispatcherTimer();
timer.Tick += (s, e) => { inc = (inc + 0.05) % 360; Refresh(); };
timer.Interval = new TimeSpan(0, 0, 0, 0, 40);
timer.Start();
}
private void DrawSpiral(Graphics g, int len, double angleIncrement)
{
double x1 = Width / 2;
double y1 = Height / 2;
double angle = angleIncrement;
for (int i = 0; i < 150; i++)
{
double x2 = x1 + Math.Cos(angle) * len;
double y2 = y1 - Math.Sin(angle) * len;
g.DrawLine(Pens.Blue, (int)x1, (int)y1, (int)x2, (int)y2);
x1 = x2;
y1 = y2;
len += 3;
angle = (angle + angleIncrement) % (Math.PI * 2);
}
}
protected override void OnPaint(PaintEventArgs args)
{
var g = args.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Clear(Color.White);
DrawSpiral(g, 5, ToRadians(inc));
}
private double ToRadians(double angle)
{
return Math.PI * angle / 180.0;
}
}
}
C++
This Windows programm has no animation, it will simply save 100 bitmaps onto your harddrive
#include <windows.h>
#include <sstream>
#include <ctime>
const float PI = 3.1415926536f, TWO_PI = 2.f * PI;
class vector2
{
public:
vector2( float a = 0, float b = 0 ) { set( a, b ); }
void set( float a, float b ) { x = a; y = b; }
void rotate( float r ) {
float _x = x, _y = y,
s = sinf( r ), c = cosf( r ),
a = _x * c - _y * s, b = _x * s + _y * c;
x = a; y = b;
}
vector2 add( const vector2& v ) {
x += v.x; y += v.y;
return *this;
}
float x, y;
};
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;
};
int main( int argc, char* argv[] ) {
srand( unsigned( time( 0 ) ) );
myBitmap bmp;
bmp.create( 600, 600 ); bmp.clear();
HDC dc = bmp.getDC();
float fs = ( TWO_PI ) / 100.f;
int index = 0;
std::string a = "f://users//images//test", b;
float ang, len;
vector2 p1, p2;
for( float step = 0.1f; step < 5.1f; step += .05f ) {
ang = 0; len = 2;
p1.set( 300, 300 );
bmp.setPenColor( RGB( rand() % 50 + 200, rand() % 300 + 220, rand() % 50 + 200 ) );
for( float xx = 0; xx < TWO_PI; xx += fs ) {
MoveToEx( dc, (int)p1.x, (int)p1.y, NULL );
p2.set( 0, len ); p2.rotate( ang ); p2.add( p1 );
LineTo( dc, (int)p2.x, (int)p2.y );
p1 = p2; ang += step; len += step;
}
std::ostringstream ss; ss << index++;
b = a + ss.str() + ".bmp";
bmp.saveBitmap( b );
bmp.clear();
}
return 0;
}
Ceylon
Be sure to import javafx.graphics and ceylon.numeric in your module.ceylon file.
import javafx.application {
Application
}
import javafx.stage {
Stage
}
import javafx.animation {
AnimationTimer
}
import ceylon.numeric.float {
remainder,
cos,
sin,
toRadians
}
import javafx.scene.layout {
BorderPane
}
import javafx.scene.canvas {
Canvas
}
import javafx.scene {
Scene
}
import javafx.scene.paint {
Color
}
shared void run() {
Application.launch(`PolySpiralApp`);
}
shared class PolySpiralApp() extends Application() {
value width = 600.0;
value height = 600.0;
variable value incr = 0.0;
shared actual void start(Stage primaryStage) {
value canvas = Canvas(width, height);
value graphics = canvas.graphicsContext2D;
object extends AnimationTimer() {
shared actual void handle(Integer now) {
incr = remainder(incr + 0.05, 360.0);
variable value x = width / 2.0;
variable value y = width / 2.0;
variable value length = 5.0;
variable value angle = incr;
graphics.fillRect(0.0, 0.0, width, height);
graphics.beginPath();
graphics.moveTo(x, y);
for (i in 1..150) {
value radians = toRadians(angle);
x = x + cos(radians) * length;
y = y + sin(radians) * length;
graphics.stroke = Color.hsb(angle, 1.0, 1.0);
graphics.lineTo(x, y);
length += 3;
angle = remainder(angle + incr, 360.0);
}
graphics.stroke();
}
}.start();
value root = BorderPane();
root.center = canvas;
value scene = Scene(root);
primaryStage.title = "poly-spiral";
primaryStage.setScene(scene);
primaryStage.show();
}
}
Delphi
![](http://static.miraheze.org/rosettacodewiki/1/18/DelphiSpiralAnimaion.png)
procedure PolySpiral(Image: TImage);
var Step,Angle,LineLen,I: integer;
var X,Y,X1,Y1: double;
begin
AbortFlag:=False;
ClearImage(Image,clBlack);
Image.Canvas.Pen.Width:=1;
while true do
begin
Image.Canvas.Pen.Color:=clYellow;
Step:=(Step + 5) mod 360;
X:=Image.Width/2;
Y:=Image.Height/2;
LineLen:=5;
angle:=Step;
for I:=1 to 150 do
begin
X1:=X + LineLen*cos(DegToRad(angle));
Y1:=Y + LineLen*sin(DegToRad(angle));
Image.Canvas.MoveTo(Round(X),Round(Y));
Image.Canvas.LIneTo(Round(X1),Round(Y1));
Image.Repaint;
LineLen:=LineLen+2;
Angle:=(Angle + Step) mod 360;
X:=X1;
Y:=Y1;
end;
if Application.Terminated then exit;
if AbortFlag then break;
Sleep(1200);
Application.ProcessMessages;
WaitForButton;
ClearImage(Image,clBlack);
end;
end;
- Output:
EasyLang
color 944
linewidth 0.3
on animate
clear
incr = (incr + 0.05) mod 360
x1 = 50
y1 = 50
length = 1
angle = incr
move x1 y1
for i = 1 to 150
x2 = x1 + cos angle * length
y2 = y1 + sin angle * length
line x2 y2
x1 = x2
y1 = y2
length += 1
angle = (angle + incr) mod 360
.
.
FreeBASIC
#include "fbgfx.bi"
#if __FB_LANG__ = "fb"
Using FB '' Scan code constants are stored in the FB namespace in lang FB
#endif
#define pi 4 * Atn(1)
#define Deg2Rad pi/180
Dim As Integer w = 900, h = w
Screenres w, h, 8
Windowtitle "Polyspiral"
Dim As Integer incr = 0, angulo, longitud, x1, y1, x2, y2, N
Do
incr += 1
x1 = w / 2
y1 = h / 2
Pset (Fix(x1), Fix(y1))
longitud = 5
angulo = incr
For N = 1 To 150
x2 = x1 + longitud * Cos(angulo * Deg2Rad)
y2 = y1 + longitud * Sin(angulo * Deg2Rad)
Line - (Fix(x2), Fix(y2)), N+16
x1 = x2
y1 = y2
longitud += 3
angulo += incr
Next N
Sleep 500
Cls
Loop Until Multikey(SC_ESCAPE)
FutureBasic
local fn DoIt
NSInteger i, t
double length, incr, x1, y1, x2, y2, twopi, angle, w, h
pen 2.0, fn ColorRed, NSLineCapStyleButt, NULL, 0
incr = 0 : twopi = 2 * pi
w = 600 : h = 600
t = 150
while ( t > 0 )
incr = ( incr + 0.05 mod twopi )
x1 = w / 2
y1 = h / 2
length = 1.0
angle = incr
line to x1, y1
cls
for i = 1 to 300
x2 = x1 + cos( angle ) * length
y2 = y1 + sin( angle ) * length
line to x1, y1 to x2, y2
x1 = x2 : y1 = y2
length = length + 1.0
angle = ( angle + incr mod twopi )
next
t--
wend
end fn
window 1, @"Rosetta Code Polyspiral", fn CGRectMake( 0, 0, 600, 600 )
WindowSetBackgroundColor( 1, fn ColorBlack )
fn DoIt
HandleEvents
- Output:
Fōrmulæ
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.
Programs in Fōrmulæ are created/edited online in its website.
In this page you can see and run the program(s) related to this task and their results. You can also change either the programs or the parameters they are called with, for experimentation, but remember that these programs were created with the main purpose of showing a clear solution of the task, and they generally lack any kind of validation.
Solution
Test cases
Gnuplot
Plotting a polyspiral file-function for the load command
plotpoly.gp file for the load command is the only possible imitation of the fine function in the gnuplot.
## plotpoly.gp 1/10/17 aev
## Plotting a polyspiral and writing to the png-file.
## Note: assign variables: rng, d, clr, filename and ttl (before using load command).
## Direction d (-1 clockwise / 1 counter-clockwise)
reset
set terminal png font arial 12 size 640,640
ofn=filename.".png"
set output ofn
unset border; unset xtics; unset ytics; unset key;
set title ttl font "Arial:Bold,12"
set parametric
c=rng*pi; set xrange[-c:c]; set yrange[-c:c];
set dummy t
plot [0:c] t*cos(d*t), t*sin(d*t) lt rgb @clr
set output
Plotting many versions of a polyspiral.
Note: only 6 versions have pictures here on RC.
## PSpirals.gp 1/10/17 aev
## Plotting many polyspiral pictures.
## Note: assign variables: rng, d, clr, filename and ttl (before using load command).
## Direction d (-1 clockwise / 1 counter-clockwise)
#cd 'C:\gnupData'
##PS0 smooth spiral (not a polyspiral)
reset
set terminal png font arial 12 size 640,640
set output "PS0gp.png"
set title "Smooth spiral #0 rng=10" font "Arial:Bold,12"
set parametric
c=10*pi; set trange [0:c]; set xrange[-c:c]; set yrange[-c:c];
set samples 1000
plot t*cos(t), t*sin(t) lt rgb "red"
set output
##PS1 A polyspiral (Same size as PS0).
rng=10; d=1; clr = '"dark-green"';
filename = "PS1gp"; ttl = "Polyspiral #1 rng=10";
load "plotpoly.gp"
##PS3 A polyspiral
rng=20; d=-1; clr = '"red"';
filename = "PS3gp"; ttl = "Polyspiral #3 rng=20";
load "plotpoly.gp"
##PS4 A polyspiral having 4 secondary spirals.
rng=50; d=-1; clr = '"navy"';
filename = "PS4gp"; ttl = "Polyspiral #4 rng=50";
load "plotpoly.gp"
##PS5 Not a polyspiral, but has 8 secondary spirals.
rng=75; d=-1; clr = '"navy"';
filename = "PS5gp"; ttl = "Polyspiral #5 rng=75";
load "plotpoly.gp"
##PS6 Not a polyspiral, just a nice figure (seen in zkl).
rng=100; d=-1; clr = '"navy"';
filename = "PS6gp"; ttl = "Polyspiral #6 rng=100";
load "plotpoly.gp"
##==============================
#### NO PICTURES on RC starting from here, test it yourself
##PS2 A polyspiral
rng=20; d=1; clr = '"red"';
filename = "PS2gp"; ttl = "Polyspiral #2 rng=20";
load "plotpoly.gp"
##PS7 Looks like PS5, but has 5 secondary spirals (not 8)
rng=120; d=-1; clr = '"green"';
filename = "PS7gp"; ttl = "Polyspiral #7 rng=120";
load "plotpoly.gp"
##PS8 Looks like PS4, but more distortion.
rng=150; d=-1; clr = '"green"';
filename = "PS8gp"; ttl = "Polyspiral #8 rng=150";
load "plotpoly.gp"
##PS9 Looks like PS2, but less loops..
rng=175; d=-1; clr = '"green"';
filename = "PS9gp"; ttl = "Polyspiral #9 rng=175";
load "plotpoly.gp"
##PS10 One loop of a spiral
rng=200; d=-1; clr = '"green"';
filename = "PS10gp"; ttl = "Polyspiral #10 rng=200";
load "plotpoly.gp"
##PS11 Polyspiral with line segments crossing other line segments.
rng=30; d=-1; clr = '"navy"';
filename = "PS11gp"; ttl = "Polyspiral #11 rng=30";
load "plotpoly.gp"
##PS12 Looks like PS4, but has 5 secondary spirals.
rng=40; d=-1; clr = '"navy"';
filename = "PS12gp"; ttl = "Polyspiral #12 rng=40";
load "plotpoly.gp"
##PS13 Looks like PS5, but has 8 secondary spirals.
rng=60; d=-1; clr = '"navy"';
filename = "PS13gp"; ttl = "Polyspiral #13 rng=60";
load "plotpoly.gp"
##PS14 Looks like PS4, but has 5 secondary spirals.
rng=80; d=-1; clr = '"navy"'
filename = "PS14gp"; ttl = "Polyspiral #14 rng=80";
load "plotpoly.gp"
##PS15 Not a polyspiral. Hmmm, just a star?
rng=90; d=-1; clr = '"navy"';
filename = "PS15gp"; ttl = "Polyspiral #15 rng=90";
load "plotpoly.gp"
##PS16 Not a polyspiral. Hmmm, just another star?
rng=300; d=-1; clr = '"navy"';
filename = "PS16gp"; ttl = "Polyspiral #16 rng=300";
load "plotpoly.gp"
## Continue plotting starting with a range rng=110 to 400+ step 10 to discover new figures.
## END ##
- Output:
1. All PSpirals.gp file commands. 2. First 6 plotted png-files: PS0gp.png - PS6gp.
Plotting a polyspiral file-function for the load command (for animation)
plotpolya.gp file for the load command is the only possible imitation of the fine function in the gnuplot.
## plotpolya.gp 1/19/17 aev
## Plotting a polyspiral and writing to the png-file. Simple plot for animation.
## Note: assign variables: rng, d, clr, filename (before using load command).
## ==== NO ttl (title) in this version.
reset
set terminal png font arial 12 size 640,640
ofn=filename.".png"
set output ofn
unset border; unset xtics; unset ytics; unset key;
set parametric
c=rng*pi; set xrange[-c:c]; set yrange[-c:c];
set dummy t
plot [0:c] t*cos(d*t), t*sin(d*t) lt rgb @clr
set output
Plotting many polyspiral and other pictures for animation.
Note: No generated pictures here on RC.
## PSpirals4a.gp 1/19/17 aev
## Plotting many polyspiral and other pictures for animation
## Notes: 1. Assign variables: rng, d, clr, filename(before using load command).
## ====== 2. NO title in this version.
## 3. Primarily range is changed.
## Direction d (-1 clockwise / 1 counter-clockwise)
#cd 'C:\gnupData'
##====== for PolySpirsAnim.gif ==========================================
##PS0 A polyspiral (direction: counter-clockwise).
rng=10; d=1; clr = '"red"'; filename = "PS0"; load "plotpolya.gp";
##PS1 A polyspiral (direction: clockwise).
rng=20; d=-1; clr = '"red"'; filename = "PS1"; load "plotpolya.gp";
##PS2 A polyspiral. Looks like PS1, but less loops..
rng=175; d=-1; clr = '"red"'; filename = "PS2"; load "plotpolya.gp";
##PS3 Polyspiral with line segments crossing other line segments.
rng=30; d=-1; clr = '"red"'; filename = "PS3"; load "plotpolya.gp";
##PS4 A polyspiral having 4 secondary spirals.
rng=50; d=-1; clr = '"red"'; filename = "PS4"; load "plotpolya.gp";
##PS5 A polyspiral. Looks like PS4, but has 5 secondary spirals.
rng=40; d=-1; clr = '"red"'; filename = "PS5"; load "plotpolya.gp";
##PS6 A polyspiral. Looks like PS4, but has more distortion.
rng=150; d=-1; clr = '"red"'; filename = "PS6"; load "plotpolya.gp";
##PS7 A polyspiral. Has 8 secondary spirals and even more distortion.
rng=60; d=-1; clr = '"red"'; filename = "PS7"; load "plotpolya.gp";
##====== for NiceFigsAnim.gif ==========================================
##PS8 Not a polyspiral, but has 8 secondary spirals.
rng=75; d=-1; clr = '"navy"'; filename = "PS8"; load "plotpolya.gp";
##PS9 Looks like PS8, but has 5 secondary spirals.
rng=80; d=-1; clr = '"navy"'; filename = "PS9"; load "plotpolya.gp";
##PS10 Looks like PS8, but has 5 secondary spirals (not 8)
rng=120; d=-1; clr = '"navy"'; filename = "PS10"; load "plotpolya.gp";
##PS11 Not a polyspiral, just nice figure.
rng=100; d=-1; clr = '"navy"'; filename = "PS11"; load "plotpolya.gp";
##PS12 Not a polyspiral. Hmmm, just a star?
rng=90; d=-1; clr = '"navy"'; filename = "PS12"; load "plotpolya.gp";
##PS13 Not a polyspiral. Hmmm, just another star?
rng=300; d=-1; clr = '"navy"'; filename = "PS13"; load "plotpolya.gp";
##PS14 Not a polyspiral, but has many short secondary spirals.
rng=700; d=-1; clr = '"navy"'; filename = "PS14"; load "plotpolya.gp";
- Output:
1. All PSpirals4a.gp file commands. 2. 15 plotted png-files: PS0.png - PS14.png.
Creating 2 animated gif-files.
Note: No gif-files. File upload still not allowed. So, test it yourself.
## Animation for polyspirals PS0 - PS6
reset
set terminal gif animate delay 100 loop 2 size 640,640
set output 'PolySpirsAnim.gif'
unset border; unset xtics; unset ytics; unset key;
unset autoscale
set xrange[0:640]
set yrange[0:640]
do for [i=0:6]{plot 'PS'.i.'.png' binary filetype=png with rgbimage}
set output
## Animation for nice figures PS8 - PS14
reset
set terminal gif animate delay 100 loop 2 size 640,640
set output 'NiceFigsAnim.gif'
unset border; unset xtics; unset ytics; unset key;
unset autoscale
set xrange[0:640]
set yrange[0:640]
do for [i=8:14]{plot 'PS'.i.'.png' binary filetype=png with rgbimage}
set output
- Output:
2 created gif-files: PolySpirsAnim.gif and NiceFigsAnim.gif
Showing 2 animated gif-files.
Create 2 the following html-files and envoke them in browser.
<!-- PolySpirsAnim.html -->
<html><body>
<h3>Gnuplot: Polyspirals animation >>
<a href="NiceFigsAnim.html">Next: Nice figures animation</a></h3>
<img src="PolySpirsAnim.gif">
</body></html>
<!-- NiceFigsAnim.html -->
<html><body>
<h3>Gnuplot: Nice figures animation >>
<a href="PolySpirsAnim.html">Next: Polyspirals animation</a></h3>
<img src="NiceFigsAnim.gif">
</body></html>
- Output:
2 pages with animation.
Go
This uses Go's 'image' packages in its standard library to create an animated GIF.
When played this is similar to the Java entry but much quicker. The whole animation completes in 72 seconds and repeats indefinitely.
Although the .gif works fine in Firefox it might not do so in EOG due to optimizations made during its creation. If so, then the following ImageMagick command should fix it:
$ convert polyspiral.gif -coalesce polyspiral2.gif $ eog polyspiral2.gif
package main
import (
"image"
"image/color"
"image/gif"
"log"
"math"
"os"
)
func drawLine(img *image.Paletted, x1, y1, x2, y2 int, ci uint8) {
var first, last int
if x2 != x1 {
m := float64(y2-y1) / float64(x2-x1)
if x1 < x2 {
first, last = x1, x2
} else {
first, last = x2, x1
}
for x := first; x <= last; x++ {
y := int(m*float64(x-x1)+0.5) + y1
img.SetColorIndex(x, y, ci)
}
} else {
if y1 < y2 {
first, last = y1, y2
} else {
first, last = y2, y1
}
for y := first; y <= last; y++ {
img.SetColorIndex(x1, y, ci)
}
}
}
func setBackgroundColor(img *image.Paletted, w, h int, ci uint8) {
for x := 0; x < w; x++ {
for y := 0; y < h; y++ {
img.SetColorIndex(x, y, ci)
}
}
}
func hsb2rgb(hue, sat, bri float64) (r, g, b int) {
u := int(bri*255 + 0.5)
if sat == 0 {
r, g, b = u, u, u
} else {
h := (hue - math.Floor(hue)) * 6
f := h - math.Floor(h)
p := int(bri*(1-sat)*255 + 0.5)
q := int(bri*(1-sat*f)*255 + 0.5)
t := int(bri*(1-sat*(1-f))*255 + 0.5)
switch int(h) {
case 0:
r, g, b = u, t, p
case 1:
r, g, b = q, u, p
case 2:
r, g, b = p, u, t
case 3:
r, g, b = p, q, u
case 4:
r, g, b = t, p, u
case 5:
r, g, b = u, p, q
}
}
return
}
func main() {
const degToRad = math.Pi / 180
const nframes = 360
const delay = 20 // 200ms
width, height := 640, 640
anim := gif.GIF{LoopCount: nframes}
rect := image.Rect(0, 0, width, height)
palette := make([]color.Color, 151)
palette[0] = color.White
for i := 1; i <= 150; i++ {
r, g, b := hsb2rgb(float64(i)/150, 1, 1)
palette[i] = color.RGBA{uint8(r), uint8(g), uint8(b), 255}
}
incr := 0
for f := 1; f <= nframes; f++ {
incr = (incr + 1) % 360
x1, y1 := width/2, height/2
length := 5.0
img := image.NewPaletted(rect, palette)
setBackgroundColor(img, width, height, 0) // white background
angle := incr
for ci := uint8(1); ci <= 150; ci++ {
x2 := x1 + int(math.Cos(float64(angle)*degToRad)*length)
y2 := y1 - int(math.Sin(float64(angle)*degToRad)*length)
drawLine(img, x1, y1, x2, y2, ci)
x1, y1 = x2, y2
length += 3
angle = (angle + incr) % 360
}
anim.Delay = append(anim.Delay, delay)
anim.Image = append(anim.Image, img)
}
file, err := os.Create("polyspiral.gif")
if err != nil {
log.Fatal(err)
}
defer file.Close()
if err2 := gif.EncodeAll(file, &anim); err != nil {
log.Fatal(err2)
}
}
Haskell
This implementation compiles to javascript that runs in the browser using the ghcjs compiler . The reflex-dom library is used to help with svg rendering and animation.
{-# LANGUAGE OverloadedStrings #-}
import Reflex
import Reflex.Dom
import Reflex.Dom.Time
import Data.Text (Text, pack)
import Data.Map (Map, fromList)
import Data.Time.Clock (getCurrentTime)
import Control.Monad.Trans (liftIO)
type Point = (Float,Float)
type Segment = (Point,Point)
main = mainWidget $ do
-- An event that fires every 0.05 seconds.
dTick <- tickLossy 0.05 =<< liftIO getCurrentTime
-- A dynamically updating counter.
dCounter <- foldDyn (\_ c -> c+1) (0::Int) dTick
let
-- A dynamically updating angle.
dAngle = fmap (\c -> fromIntegral c / 800.0) dCounter
-- A dynamically updating spiral
dSpiralMap = fmap toSpiralMap dAngle
-- svg parameters
width = 600
height = 600
boardAttrs =
fromList [ ("width" , pack $ show width)
, ("height", pack $ show height)
, ("viewBox", pack $ show (-width/2) ++ " " ++ show (-height/2) ++ " " ++ show width ++ " " ++ show height)
]
elAttr "h1" ("style" =: "color:black") $ text "Polyspiral"
elAttr "a" ("href" =: "http://rosettacode.org/wiki/Polyspiral#Haskell") $ text "Rosetta Code / Polyspiral / Haskell"
el "br" $ return ()
elSvgns "svg" (constDyn boardAttrs) (listWithKey dSpiralMap showLine)
return ()
-- The svg attributes needed to display a line segment.
lineAttrs :: Segment -> Map Text Text
lineAttrs ((x1,y1), (x2,y2)) =
fromList [ ( "x1", pack $ show x1)
, ( "y1", pack $ show y1)
, ( "x2", pack $ show x2)
, ( "y2", pack $ show y2)
, ( "style", "stroke:blue")
]
-- Use svg to display a line segment.
showLine :: MonadWidget t m => Int -> Dynamic t Segment -> m ()
showLine _ dSegment = elSvgns "line" (lineAttrs <$> dSegment) $ return ()
-- Given a point and distance/bearing , get the next point
advance :: Float -> (Point, Float, Float) -> (Point, Float, Float)
advance angle ((x,y), len, rot) =
let new_x = x + len * cos rot
new_y = y + len * sin rot
new_len = len + 3.0
new_rot = rot + angle
in ((new_x, new_y), new_len, new_rot)
-- Given an angle, generate a map of segments that form a spiral.
toSpiralMap :: Float -> Map Int ((Float,Float),(Float,Float))
toSpiralMap angle =
fromList -- changes list to map (for listWithKey)
$ zip [0..] -- annotates segments with index
$ (\pts -> zip pts $ tail pts) -- from points to line segments
$ take 80 -- limit the number of points
$ (\(pt,_,_) -> pt) -- cull out the (x,y) values
<$> iterate (advance angle) ((0, 0), 0, 0) -- compute the spiral
-- Display an element in svg namespace
elSvgns :: MonadWidget t m => Text -> Dynamic t (Map Text Text) -> m a -> m a
elSvgns t m ma = do
(el, val) <- elDynAttrNS' (Just "http://www.w3.org/2000/svg") t m ma
return val
Link to live demo: https://dc25.github.io/rosettaCode__Polyspiral_haskell/
IS-BASIC
100 PROGRAM "PolySp.bas"
110 OPTION ANGLE DEGREES
120 LET CH=2
130 SET VIDEO X 40:SET VIDEO Y 27:SET VIDEO MODE 1:SET VIDEO COLOR 0
140 OPEN #1:"video:"
150 OPEN #2:"video:"
160 WHEN EXCEPTION USE POSERROR
170 FOR ANG=40 TO 150 STEP 2
180 IF CH=2 THEN
190 LET CH=1
200 ELSE
210 LET CH=2
220 END IF
230 CLEAR #CH
240 PLOT #CH:640,468,ANGLE 180;
250 FOR D=12 TO 740 STEP 4
260 PLOT #CH:FORWARD D,RIGHT ANG;
270 NEXT
280 DISPLAY #CH:AT 1 FROM 1 TO 27
290 NEXT
300 END WHEN
310 HANDLER POSERROR
320 LET D=740
330 CONTINUE
340 END HANDLER
J
![](http://static.miraheze.org/rosettacodewiki/thumb/a/ae/J-polyspiral.gif/200px-J-polyspiral.gif)
require 'gl2 trig media/imagekit'
coinsert 'jgl2'
DT =: %30 NB. seconds
ANGLE =: 0.025p1 NB. radians
DIRECTION=: 0 NB. radians
POLY=: noun define
pc poly;pn "Poly Spiral";
minwh 320 320; cc isi isigraph;
)
poly_run=: verb define
wd POLY,'pshow'
wd 'timer ',":DT * 1000
)
poly_close=: verb define
wd 'timer 0; pclose'
)
sys_timer_z_=: verb define
recalcAngle_base_ ''
wd 'psel poly; set isi invalid'
)
poly_isi_paint=: verb define
drawPolyspiral DIRECTION
)
recalcAngle=: verb define
DIRECTION=: 2p1 | DIRECTION + ANGLE
)
drawPolyspiral=: verb define
glclear''
x1y1 =. (glqwh'')%2
a=. -DIRECTION
len=. 5
for_i. i.150 do.
glpen glrgb Hue a % 2p1
x2y2=. x1y1 + len*(cos,sin) a
gllines <.x1y1,x2y2
x1y1=. x2y2
len=. len+3
a=. 2p1 | a - DIRECTION
end.
)
poly_run''
Note that we're using a lot of wd commands here. You'll need to be running jqt for this to work.
Java
![](http://static.miraheze.org/rosettacodewiki/thumb/a/aa/Polyspiral_java2.png/300px-Polyspiral_java2.png)
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class PolySpiral extends JPanel {
double inc = 0;
public PolySpiral() {
setPreferredSize(new Dimension(640, 640));
setBackground(Color.white);
new Timer(40, (ActionEvent e) -> {
inc = (inc + 0.05) % 360;
repaint();
}).start();
}
void drawSpiral(Graphics2D g, int len, double angleIncrement) {
double x1 = getWidth() / 2;
double y1 = getHeight() / 2;
double angle = angleIncrement;
for (int i = 0; i < 150; i++) {
g.setColor(Color.getHSBColor(i / 150f, 1.0f, 1.0f));
double x2 = x1 + Math.cos(angle) * len;
double y2 = y1 - Math.sin(angle) * len;
g.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
x1 = x2;
y1 = y2;
len += 3;
angle = (angle + angleIncrement) % (Math.PI * 2);
}
}
@Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
drawSpiral(g, 5, Math.toRadians(inc));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("PolySpiral");
f.setResizable(true);
f.add(new PolySpiral(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
JavaScript
Version #1 - Plain
This Polyspiral Generator page alows user to enjoy hundreds of polyspirals in different colors.
This is inspired by a discovery made while using the gnuplot.
(See Discussion for Polyspiral task.)
Note:
- Some polyspirals would be degenerated to a single branch of it or even to a single line.
- An image uploading is still blocked. But you have a browser!? So, copy/paste/save this page and double click it.
(or any other browser supporting Canvas tag)
<!-- Polyspiral.html -->
<html>
<head><title>Polyspiral Generator</title></head>
<script>
// Basic function for family of Polyspirals
// Where: rng - range (prime parameter), w2 - half of canvas width,
// d - direction (1 - clockwise, -1 - counter clockwise).
function ppsp(ctx, rng, w2, d) {
// Note: coefficients c, it, sc, sc2, sc3 are selected to fit canvas.
var c=Math.PI*rng, it=c/w2, sc=2, sc2=50, sc3=0.1, t, x, y;
console.log("Polyspiral PARs rng,w2,d:", rng, "/", w2, "/", d);
if (rng>1000) {sc=sc3}
ctx.beginPath();
for(var i=0; i<sc2*c; i++) {
t=it*i;
x = sc*t*Math.cos(d*t)+w2; y = sc*t*Math.sin(d*t)+w2;
ctx.lineTo(x, y);
}//fend i
ctx.stroke();
}
// ******************************************
// pspiral() - Generating and plotting Polyspirals
function pspiral() {
// Setting basic vars for canvas and inpu parameters
var cvs = document.getElementById('cvsId');
var ctx = cvs.getContext("2d");
var w = cvs.width, h = cvs.height;
var w2=w/2;
var clr = document.getElementById("color").value; // color
var d = document.getElementById("dir").value; // direction
var rng = document.getElementById("rng").value; // range
rng=Number(rng);
ctx.fillStyle="white"; ctx.fillRect(0,0,w,h);
ctx.strokeStyle=clr;
// Plotting spiral.
ppsp(ctx, rng, w2, d)
}//func end
</script></head>
<body style="font-family: arial, helvatica, sans-serif;">
<b>Color: </b>
<select id="color">
<option value="red">red</option>
<option value="darkred" selected>darkred</option>
<option value="green">green</option>
<option value="darkgreen">darkgreen</option>
<option value="blue">blue</option>
<option value="navy">navy</option>
<option value="brown">brown</option>
<option value="maroon">maroon</option>
<option value="black">black</option>
</select>
<b>Direction: </b>
<input id="dir" value="1" type="number" min="-1" max="1" size="1">
<b>Range: </b>
<input id="rng" value="10" type="number" min="10" max="4000" step="10" size="4">
<input type="button" value="Plot it!" onclick="pspiral();"> <br>
<h3> Polyspiral</h3>
<canvas id="cvsId" width="640" height="640" style="border: 2px inset;"></canvas>
</body>
</html>
- Output:
Page with Polyspiral. Right-clicking on the canvas you can save spiral as a png-file, for example. Try all ranges/colors! But particularly these ranges: 50, 70, 80, 90, 110, 130, 160, 210, 220, 240, 270, 280, 290, 300, 310, 330, 340, 350, 400, 430, 480, 510, all 1010-2000, a few 3000+, etc.
Version #2 - Animated
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
body {
background-color: black;
}
</style>
</head>
<body>
<canvas></canvas>
<script>
var canvas = document.querySelector("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var g = canvas.getContext("2d");
var inc = 0;
function drawSpiral(len, angleIncrement) {
var x1 = canvas.width / 2;
var y1 = canvas.height / 2;
var angle = angleIncrement;
for (var i = 0; i < 150; i++) {
var x2 = x1 + Math.cos(angle) * len;
var y2 = y1 - Math.sin(angle) * len;
g.strokeStyle = HSVtoRGB(i / 150, 1.0, 1.0);
g.beginPath();
g.moveTo(x1, y1);
g.lineTo(x2, y2);
g.stroke();
x1 = x2;
y1 = y2;
len += 3;
angle = (angle + angleIncrement) % (Math.PI * 2);
}
}
/* copied from stackoverflow */
function HSVtoRGB(h, s, v) {
var r, g, b, i, f, p, q, t;
i = Math.floor(h * 6);
f = h * 6 - i;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
return "rgb("
+ Math.round(r * 255) + ","
+ Math.round(g * 255) + ","
+ Math.round(b * 255) + ")";
}
function toRadians(degrees) {
return degrees * (Math.PI / 180);
}
setInterval(function () {
inc = (inc + 0.05) % 360;
g.clearRect(0, 0, canvas.width, canvas.height);
drawSpiral(5, toRadians(inc));
}, 40);
</script>
</body>
</html>
Julia
using Gtk, Graphics, Colors
const can = @GtkCanvas()
const win = GtkWindow(can, "Polyspiral", 360, 360)
const drawiters = 72
const colorseq = [colorant"blue", colorant"red", colorant"green", colorant"black", colorant"gold"]
const angleiters = [0, 0, 0]
const angles = [75, 100, 135, 160]
Base.length(v::Vec2) = sqrt(v.x * v.x + v.y * v.y)
function drawline(ctx, p1, p2, color, width=1)
move_to(ctx, p1.x, p1.y)
set_source(ctx, color)
line_to(ctx, p2.x, p2.y)
set_line_width(ctx, width)
stroke(ctx)
end
@guarded draw(can) do widget
δ(r, θ) = Vec2(r * cospi(θ/180), r * sinpi(θ/180))
nextpoint(p, r, θ) = (dp = δ(r, θ); Point(p.x + dp.x, p.y + dp.y))
colorindex = (angleiters[1] % 5) + 1
colr = colorseq[colorindex]
ctx = getgc(can)
h = height(can)
w = width(can)
x = 0.5 * w
y = 0.5 * h
θ = angleiters[2] * rand() * 3
δθ = angleiters[2]
r = 5
δr = 3
p1 = Point(x, y)
for i in 1:drawiters
if angleiters[3] == 0
set_source(ctx, colorant"gray90")
rectangle(ctx, 0, 0, w, h)
fill(ctx)
continue
end
p2 = nextpoint(p1, r, θ)
drawline(ctx, p1, p2, colr, 2)
θ = θ + δθ
r = r + δr
p1 = p2
end
end
show(can)
while true
angleiters[2] = angles[angleiters[1] % 3 + 1]
angleiters[1] += 1
angleiters[3] = angleiters[3] == 0 ? 1 : 0
draw(can)
yield()
sleep(0.5)
end
Kotlin
// version 1.1.0
import java.awt.*
import java.awt.event.ActionEvent
import javax.swing.*
class PolySpiral() : JPanel() {
private var inc = 0.0
init {
preferredSize = Dimension(640, 640)
background = Color.white
Timer(40) {
inc = (inc + 0.05) % 360.0
repaint()
}.start()
}
private fun drawSpiral(g: Graphics2D, length: Int, angleIncrement: Double) {
var x1 = width / 2.0
var y1 = height / 2.0
var len = length
var angle = angleIncrement
for (i in 0 until 150) {
g.setColor(Color.getHSBColor(i / 150f, 1.0f, 1.0f))
val x2 = x1 + Math.cos(angle) * len
val y2 = y1 - Math.sin(angle) * len
g.drawLine(x1.toInt(), y1.toInt(), x2.toInt(), y2.toInt())
x1 = x2
y1 = y2
len += 3
angle = (angle + angleIncrement) % (Math.PI * 2.0)
}
}
override protected fun paintComponent(gg: Graphics) {
super.paintComponent(gg)
val g = gg as Graphics2D
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
drawSpiral(g, 5, Math.toRadians(inc))
}
}
fun main(args: Array<String>) {
SwingUtilities.invokeLater {
val f = JFrame()
f.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
f.title = "PolySpiral"
f.setResizable(true)
f.add(PolySpiral(), BorderLayout.CENTER)
f.pack()
f.setLocationRelativeTo(null)
f.setVisible(true)
}
}
Lua
LÖVE defaults to animating at sixty frames per second, so the patterns become very complex very quickly.
function love.load ()
love.window.setTitle("Polyspiral")
incr = 0
end
function love.update (dt)
incr = (incr + 0.05) % 360
x1 = love.graphics.getWidth() / 2
y1 = love.graphics.getHeight() / 2
length = 5
angle = incr
end
function love.draw ()
for i = 1, 150 do
x2 = x1 + math.cos(angle) * length
y2 = y1 + math.sin(angle) * length
love.graphics.line(x1, y1, x2, y2)
x1, y1 = x2, y2
length = length + 3
angle = (angle + incr) % 360
end
end
Mathematica/Wolfram Language
linedata = {};
Dynamic[Graphics[Line[linedata], PlotRange -> 1000]]
Do[
linedata = AnglePath[{#, \[Theta]} & /@ Range[5, 300, 3]];
Pause[0.1];
,
{\[Theta], Subdivide[0.1, 1, 100]}
]
- Output:
Outputs an animating graphic with a spiral with changing angle.
Nim
As Julia, we use Gtk/Cairo to draw the polyspirals. So, the drawing part is taken, with some modifications, from Julia solution.
# Pendulum simulation.
import math, random
import gintro/[gobject, gdk, gtk, gio, glib, cairo]
const
Width = 500
Height = 500
DrawIters = 72
Red = [float 1, 0, 0]
Green = [float 0, 1, 0]
Blue = [float 0, 0, 1]
Black = [float 0, 0, 0]
White = [float 255, 255, 255]
Gold = [float 255, 215, 0]
Colors = [Blue, Red, Green, White, Gold]
Angles = [75, 100, 135, 160]
type
Vec2 = tuple[x, y: float]
Point = Vec2
# Description of the simulation.
Simulation = ref object
area: DrawingArea
xmax, ymax: float
center: Point
itercount: int
#---------------------------------------------------------------------------------------------------
proc newSimulation(area: DrawingArea; width, height: int): Simulation {.noInit.} =
## Allocate and initialize the simulation object.
new(result)
result.area = area
result.xmax = float(width - 1)
result.ymax = float(height - 1)
result.center = (result.xmax * 0.5, result.ymax * 0.5)
#---------------------------------------------------------------------------------------------------
func δ(r, θ: float): Vec2 = (r * cos(degToRad(θ)), r * sin(degToRad(θ)))
#---------------------------------------------------------------------------------------------------
func nextPoint(p: Point; r, θ: float): Point =
let dp = δ(r, θ)
result = (p.x + dp.x, p.y + dp.y)
#---------------------------------------------------------------------------------------------------
proc draw(sim: Simulation; context: cairo.Context) =
## Draw the spiral.
context.setSource(Black)
context.rectangle(0, 0, sim.xmax, sim.ymax)
context.fill()
let colorIndex = sim.itercount mod Colors.len
let color = Colors[colorIndex]
var p1 = sim.center
let δθ = Angles[sim.itercount mod Angles.len].toFloat
var θ = δθ * rand(1.0) * 3
var r = 5.0
let δr = 3.0
for _ in 1..DrawIters:
let p2 = p1.nextPoint(r, θ)
context.moveTo(p1.x, p1.y)
context.setSource(color)
context.lineTo(p2.x, p2.y)
context.setLineWidth(2)
context.stroke()
θ += δθ
r += δr
p1 = p2
#---------------------------------------------------------------------------------------------------
proc update(sim: Simulation): gboolean =
## Update the simulation state.
result = gboolean(1)
sim.draw(sim.area.window.cairoCreate())
inc sim.itercount
#---------------------------------------------------------------------------------------------------
proc activate(app: Application) =
## Activate the application.
let window = app.newApplicationWindow()
window.setSizeRequest(Width, Height)
window.setTitle("Polyspiral")
let area = newDrawingArea()
window.add(area)
let sim = newSimulation(area, Width, Height)
timeoutAdd(500, update, sim)
window.showAll()
#———————————————————————————————————————————————————————————————————————————————————————————————————
let app = newApplication(Application, "Rosetta.polyspiral")
discard app.connect("activate", activate)
discard app.run()
PARI/GP
Plotting helper functions
Both versions #1 and #2 are based on using my own small plotting helper functions. You can find a few others on OEIS Wiki and here on RC Wiki.
\\ Plot the line from x1,y1 to x2,y2.
plotline(x1,y1,x2,y2,w=0)={plotmove(w, x1,y1);plotrline(w,x2-x1,y2-y1);}
\\ Convert degrees to radians.
rad2(degs)={return(degs*Pi/180.0)}
\\ Convert Polar coordinates to Cartesian.
cartes2(r,a,rndf=0)={my(v,x,y); x=r*cos(a); y=r*sin(a);
if(rndf==0, return([x,y]), return(round([x,y])))}
Version #1. Polyspiral (a spiral made of multiple line segments).
In this version function plotpspiral() was translated from Java and J. Some tweaks and options were added to make it reusable and outputting differently looking polyspirals. There are no animation features in PARI/GP.
![](http://static.miraheze.org/rosettacodewiki/thumb/0/03/Polyspiral1.png/100px-Polyspiral1.png)
![](http://static.miraheze.org/rosettacodewiki/thumb/5/56/Polyspiral2.png/100px-Polyspiral2.png)
![](http://static.miraheze.org/rosettacodewiki/thumb/4/4b/Polyspiral3.png/100px-Polyspiral3.png)
![](http://static.miraheze.org/rosettacodewiki/thumb/d/df/Polyspiral3b.png/100px-Polyspiral3b.png)
![](http://static.miraheze.org/rosettacodewiki/thumb/0/0d/Polyspiral4.png/100px-Polyspiral4.png)
\\Polyspiral (a spiral made of multiple line segments)
\\ 4/15/16 aev
plotpspiral(size,lim,ai,d,di,c)={
my(x1,y1,x2,y2,air=ai*Pi,a,sai=Strprintf("%.3f",ai));
print(" *** Polyspiral, size=",size," lim=",lim," ai=",sai," d=",d," di=",di);
x1=0; y1=0;
a=air;
for(i=0, lim,
if(c==0, x2=x1+cos(a)*d; y2=y1-sin(a)*d,
x2=x1-sin(a)*d; y2=y1+cos(a)*d;);
plotline(x1,y1,x2,y2);
x1=x2; y1=y2; d+=di; a+=air;
);\\fend i
}
\\ Polyspiral() - Where: ai is an angle increment (in radians), d is a distance/length,
\\ c is a direction 0/1 (clockwise/counter-clockwise); other parameters are self explanative.
\\ 4/15/16 aev Last updated: 4/18/16
polyspiral(size,lim,ai,d,di,c=0)={
plotinit(0);
plotcolor(0,3); \\blue
plotscale(0, -size,size, -size,size);
plotmove(0, 0,0);
plotpspiral(size,lim,ai,d,di,c);
plotdraw([0,size,size]);
}
{\\ Executing:
polyspiral(1500,1500,0.25,9,5); \\Polyspiral1.png
polyspiral(1500,1500,0.25,3,2); \\Polyspiral2.png
polyspiral(10000,10000,0.03,3,2); \\Polyspiral3.png
polyspiral(10000,10000,0.03,3,2,1); \\Polyspiral3b.png
polyspiral(100000,100000,0.03,3,2);\\Polyspiral4.png
}
- Output:
> polyspiral(1500,1500,0.25,9,5); \\Polyspiral1.png *** Polyspiral, size=1500 lim=1500 ai=0.250 d=9 di=5 > polyspiral(1500,1500,0.25,3,2); \\Polyspiral2.png *** Polyspiral, size=1500 lim=1500 ai=0.250 d=3 di=2 > polyspiral(10000,10000,0.03,3,2); \\Polyspiral3.png *** Polyspiral, size=100000 lim=100000 ai=0.030 d=3 di=2 > polyspiral(10000,10000,0.03,3,2,1); \\Polyspiral3b.png *** Polyspiral, size=100000 lim=100000 ai=0.030 d=3 di=2 > polyspiral(100000,100000,0.03,3,2); \\Polyspiral4.png *** Polyspiral, size=100000 lim=100000 ai=0.030 d=3 di=2
Version #2. Multi-spiral figure translated from zkl.
This is definitely not a polyspiral, but a very nice "multi-spiral" figure similar to shown in zkl and in a few other languages. Also, there is a very nice and impressive animation created in zkl, but not possible in PARI/GP.
![](http://static.miraheze.org/rosettacodewiki/thumb/4/4f/Spiralz1.png/100px-Spiralz1.png)
\\ plotpspiralz() Multi-spiral figure translated from zkl using my own ploting functions.
\\ 4/15/16 aev
plotpspiralz(size,lim,ai,di,lim2)={
my(x1,y1,u1,v1,air=rad2(ai),a,sai=Strprintf("%.3f",ai),sdi=Strprintf("%.3f",di),
sz2=size\2,aj,inc,ao,x,y,u,v,vc,r2i=rad2(130.0),d=0.0);
print(" *** Spiralz: size=",size," lim=",lim," ai=",sai," di=",sdi," lim2=",lim2);
x1=0; y1=0; u1=0; v1=0;
for(i=1, lim,
r=0.0; a=0.0;ao=0.0;
if(i>1, inc=air+r2i, inc=air);
for(j=1, lim2,
d=r+di; aj=a+inc;
vc=cartes2(r,a); x=vc[1]; y=vc[2];
vc=cartes2(r,aj); u=vc[1]; v=vc[2];
plotline(ao+x,ao+y,ao+u,ao+v);
r=d; a=aj;
);\\fend j
air+=0.05;
);\\fend i
}
\\ Spiralz() - Where: ai is an angle increment (in radians), di is a distance/length
\\ increment, other parameters are self explanative.
\\ 4/15/16 aev
Spiralz(size,lim,ai,di,lim2)={
plotinit(0); plotcolor(0,3); \\blue
plotscale(0, -size,size, -size,size);
\\plotscale(0, 0,size, 0,size);
plotmove(0, 0,0);
plotpspiralz(size,lim,ai,di,lim2);
plotdraw([0,size,size]);
}
{\\ Executing:
Spiralz(640,2,3.0,3.0,128); \\Spiralz1.png
}
- Output:
> Spiralz(640,2,3.0,3.0,128); \\Spiralz1.png *** Spiralz: size=640 lim=2 ai=3.000 di=3.000 lim2=128
Perl
Click Start button to run, then runs continuously. It takes just a little over four minutes to complete a full 360 degree cycle.
#!/usr/bin/perl
use strict; # https://rosettacode.org/wiki/Polyspiral
use warnings;
use Tk;
use List::Util qw( min );
my $size = 500;
my ($width, $height, $x, $y, $dist);
my $angleinc = 0;
my $active = 0;
my $wait = 1000 / 30;
my $radian = 90 / atan2 1, 0;
my $mw = MainWindow->new;
$mw->title( 'Polyspiral' );
my $c = $mw->Canvas( -width => $size, -height => $size,
-relief => 'raised', -borderwidth => 2,
)->pack(-fill => 'both', -expand => 1);
$mw->bind('<Configure>' => sub { $width = $c->width; $height = $c->height;
$dist = min($width, $height) ** 2 / 4 } );
$mw->Button(-text => $_->[0], -command => $_->[1],
)->pack(-side => 'right') for
[ Exit => sub {$mw->destroy} ],
[ 'Start / Pause' => sub { $active ^= 1; step() } ];
MainLoop;
-M $0 < 0 and exec $0;
sub step
{
$active or return;
my @pts = ($x = $width >> 1, $y = $height >> 1);
my $length = 5;
my $angle = $angleinc;
$angleinc += 0.05 / $radian;
while( ($x - $width / 2)**2 + ($y - $height / 2)**2 < $dist && @pts < 300 )
{
push @pts, $x, $y;
$x += $length * cos($angle);
$y += $length * sin($angle);
$length += 3;
$angle += $angleinc;
}
$c->delete('all');
$c->createLine( @pts );
$mw->after($wait => \&step);
}
Phix
Space toggles the timer, '+' increases speed (up to 100 FPS), '-' decreases speed. 'M' toggles "mod360", which inverts the angle every 360/2PI or so, since sin/cos accept arguments in radians not degrees (and mod 2*PI changes nothing), producing non-true polyspirals, but quite interesting nevertheless. You can run this online here.
-- -- demo\rosetta\Polyspiral.exw -- =========================== -- -- Space toggles the timer, '+' increases speed (up to 100 FPS), '-' decreases speed -- 'M' toggles "mod360", which inverts the angle every 360/2PI or so, since sin/cos -- accept arguments in radians not degrees (and mod 2*PI changes nothing), producing -- non-true polyspirals, but quite interesting nevertheless. -- with javascript_semantics constant TITLE = "Polyspiral" include pGUI.e Ihandle dlg, canvas, timer cdCanvas cddbuffer, cdcanvas atom incr = 0 bool mod360 = false procedure Polyspiral(atom x1, y1) atom angle = incr integer len = 5 incr += 0.05 if mod360 then incr = mod(incr,360) end if for i=1 to 150 do atom x2 = x1 + cos(angle)*len, y2 = y1 + sin(angle)*len cdCanvasSetForeground(cddbuffer, i*#200+i*#40+i*#10) cdCanvasLine(cddbuffer, x1, y1, x2, y2) {x1, y1} = {x2, y2} len += 3 angle += incr if mod360 then angle = mod(angle,360) end if end for end procedure function redraw_cb(Ihandle /*ih*/) integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE") cdCanvasActivate(cddbuffer) cdCanvasClear(cddbuffer) Polyspiral(w/2, h/2) cdCanvasFlush(cddbuffer) integer ms = IupGetInt(timer,"TIME") IupSetStrAttribute(dlg, "TITLE", "%s (timer=%d [%g FPS], angle %3.2f%s)", {TITLE,ms,1000/ms,incr,iff(mod360?" (mod360)":"")}) return IUP_DEFAULT end function function timer_cb(Ihandle /*timer*/) IupUpdate(canvas) return IUP_IGNORE end function function map_cb(Ihandle canvas) cdcanvas = cdCreateCanvas(CD_IUP, canvas) cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas) cdCanvasSetBackground(cddbuffer, CD_WHITE) cdCanvasSetForeground(cddbuffer, CD_GRAY) return IUP_DEFAULT end function function key_cb(Ihandle /*ih*/, atom c) if c=K_ESC then return IUP_CLOSE end if if c=' ' then IupSetInt(timer,"RUN",not IupGetInt(timer,"RUN")) elsif find(c,"+-") then IupSetInt(timer,"RUN",false) c = -(','-c) -- ('+' ==> +1, '-' ==> -1) IupSetInt(timer,"TIME",max(10,IupGetInt(timer,"TIME")+c*10)) IupSetInt(timer,"RUN",true) elsif upper(c)='M' then mod360 = not mod360 end if return IUP_CONTINUE end function IupOpen() canvas = IupCanvas("RASTERSIZE=640x640") IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"), "ACTION", Icallback("redraw_cb")}) timer = IupTimer(Icallback("timer_cb"), 20) dlg = IupDialog(canvas,`TITLE="%s"`, {TITLE}) IupSetCallback(dlg, "KEY_CB", Icallback("key_cb")) IupShow(dlg) IupSetAttribute(canvas, "RASTERSIZE", NULL) if platform()!=JS then IupMainLoop() IupClose() end if
Processing
//Aamrun, 2nd July 2022
int incr = 0, angle, i, length;
float x,y,x1,y1;
double factor = PI/180;
void setup() {
size(1000, 1000);
stroke(255);
}
void draw() {
background(51);
incr = (incr + 5)%360;
x = width/2;
y = height/2;
length = 5;
angle = incr;
for(i=1;i<=150;i++){
x1 = x + (float)(length*Math.cos(factor*angle));
y1 = y + (float)(length*Math.sin(factor*angle));
line(x,y,x1,y1);
length += 3;
angle = (angle + incr)%360;
x = x1;
y = y1;
}
}
Python
import math
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((1024, 600))
pygame.display.set_caption("Polyspiral")
incr = 0
running = True
while running:
pygame.time.Clock().tick(60)
for event in pygame.event.get():
if event.type==QUIT:
running = False
break
incr = (incr + 0.05) % 360
x1 = pygame.display.Info().current_w / 2
y1 = pygame.display.Info().current_h / 2
length = 5
angle = incr
screen.fill((255,255,255))
for i in range(1,151):
x2 = x1 + math.cos(angle) * length
y2 = y1 + math.sin(angle) * length
pygame.draw.line(screen, (255,0,0), (x1, y1), (x2, y2), 1)
# pygame.draw.aaline(screen, (255,0,0), (x1, y1), (x2, y2)) # Anti-Aliased
x1, y1 = x2, y2
length += 3
angle = (angle + incr) % 360
pygame.display.flip()
Quackery
[ $ "turtleduck.qky" loadfile ] now!
[ 1000 * time +
[ dup time < until ]
drop ] is ms ( n --> )
[ turtle 0 frames
3601 times
[ clear
i^ 3600
1000 times
[ i^ 1+ 1 walk
2dup turn ]
2drop
frame
10 ms ] ] is polyspiral ( --> )
- Output:
Racket
Uses the *universe* animation
#lang racket
(require 2htdp/universe pict racket/draw)
(define ((polyspiral width height segment-length-increment n-segments) tick/s/28)
(define turn-angle (degrees->radians (/ tick/s/28 8)))
(pict->bitmap
(dc (λ (dc dx dy)
(define old-brush (send dc get-brush))
(define old-pen (send dc get-pen))
(define path (new dc-path%))
(define x (/ width #i2))
(define y (/ height #i2))
(send path move-to x y)
(for/fold ((x x) (y y) (l segment-length-increment) (a #i0))
((seg n-segments))
(define x′ (+ x (* l (cos a))))
(define y′ (+ y (* l (sin a))))
(send path line-to x y)
(values x′ y′ (+ l segment-length-increment) (+ a turn-angle)))
(send dc draw-path path dx dy)
(send* dc (set-brush old-brush) (set-pen old-pen)))
width height)))
(animate (polyspiral 400 400 2 1000))
See the output for yourself!
Raku
(formerly Perl 6)
SVG "pseudo-animation"
Sort of an ersatz animation. Write updates to a svg file, most modern viewers will update as the content changes.
use SVG;
my $w = 600;
my $h = 600;
for 3..33 -> $a {
my $angle = $a/τ;
my $x1 = $w/2;
my $y1 = $h/2;
my @lines;
for 1..144 {
my $length = 3 * $_;
my ($x2, $y2) = ($x1, $y1) «+« |cis($angle * $_).reals».round(.01) »*» $length ;
@lines.push: 'line' => [:x1($x1.clone), :y1($y1.clone), :x2($x2.clone), :y2($y2.clone),
:style("stroke:rgb({hsv2rgb(($_*5 % 360)/360,1,1).join: ','})")];
($x1, $y1) = $x2, $y2;
}
my $fname = "./polyspiral-perl6.svg".IO.open(:w);
$fname.say( SVG.serialize(
svg => [
width => $w, height => $h, style => 'stroke:rgb(0,0,0)',
:rect[:width<100%>, :height<100%>, :fill<black>],
|@lines,
],)
);
$fname.close;
sleep .15;
}
sub hsv2rgb ( $h, $s, $v ){ # inputs normalized 0-1
my $c = $v * $s;
my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
my $m = $v - $c;
my ($r, $g, $b) = do given $h {
when 0..^(1/6) { $c, $x, 0 }
when 1/6..^(1/3) { $x, $c, 0 }
when 1/3..^(1/2) { 0, $c, $x }
when 1/2..^(2/3) { 0, $x, $c }
when 2/3..^(5/6) { $x, 0, $c }
when 5/6..1 { $c, 0, $x }
}
( $r, $g, $b ).map: ((*+$m) * 255).Int
}
- Output:
See polyspiral-perl6.gif (offsite animated gif image)
SDL full animation
Uses the same basic algorithm but fully animated. Use the up / down arrow keys to speed up / slow down the update speed. Use PgUp / PgDn keys to increment / decrement animation speed by large amounts. Use left / right arrow keys to reverse the "direction" of angle change. Press Space bar to toggle animation / reset to minimum speed. Left Control key to toggle stationary / rotating center. Use + / - keys to add remove line segments.
use SDL2::Raw;
my $width = 900;
my $height = 900;
SDL_Init(VIDEO);
my $window = SDL_CreateWindow(
'Polyspiral',
SDL_WINDOWPOS_CENTERED_MASK,
SDL_WINDOWPOS_CENTERED_MASK,
$width, $height,
RESIZABLE
);
my $render = SDL_CreateRenderer($window, -1, ACCELERATED +| PRESENTVSYNC);
my $event = SDL_Event.new;
enum KEY_CODES (
K_UP => 82,
K_DOWN => 81,
K_LEFT => 80,
K_RIGHT => 79,
K_SPACE => 44,
K_PGUP => 75,
K_PGDN => 78,
K_LCTRL => 224,
K_PLUS => 87,
K_MINUS => 86,
K_SPLUS => 46,
K_SMINUS => 45,
);
my $angle = 0;
my $lines = 240;
my @rgb = palette($lines);
my ($x1, $y1);
my $dir = 1;
my $rot = 0;
my $incr = .0001/π;
my $step = $incr*70;
main: loop {
while SDL_PollEvent($event) {
my $casted_event = SDL_CastEvent($event);
given $casted_event {
when *.type == QUIT { last main }
when *.type == KEYDOWN {
if KEY_CODES(.scancode) -> $comm {
given $comm {
when 'K_LEFT' { $dir = $rot ?? 1 !! -1 }
when 'K_RIGHT' { $dir = $rot ?? -1 !! 1 }
when 'K_UP' { $step += $incr }
when 'K_DOWN' { $step -= $incr if $step > $incr }
when 'K_PGUP' { $step += $incr*50 }
when 'K_PGDN' { $step -= $incr*50; $step = $step < $incr ?? $incr !! $step }
when 'K_SPACE' { $step = $step ?? 0 !! $incr }
when 'K_LCTRL' { $rot = $rot ?? 0 !! -1; $dir *= -1 }
when 'K_PLUS' { $lines = ($lines + 5) min 360; @rgb = palette($lines) }
when 'K_SPLUS' { $lines = ($lines + 5) min 360; @rgb = palette($lines) }
when 'K_MINUS' { $lines = ($lines - 5) max 60; @rgb = palette($lines) }
when 'K_SMINUS' { $lines = ($lines - 5) max 60; @rgb = palette($lines) }
}
}
#say .scancode; # unknown key pressed
}
when *.type == WINDOWEVENT {
if .event == 5 {
$width = .data1;
$height = .data2;
}
}
}
}
$angle = ($angle + $dir * $step) % τ;
($x1, $y1) = $width div 2, $height div 2;
my $dim = $width min $height;
my $scale = (2 + .33 * abs(π - $angle)) * $dim / $lines;
$scale *= ($angle > π) ?? (1 - $angle/τ) !! $angle/τ;
$scale max= $dim/$lines/$lines;
for ^$lines {
my $length = $scale + $scale * $_;
my ($x2, $y2) = ($x1, $y1) «+« cis(($angle * $rot * $lines) + $angle * $_).reals »*» $length;
SDL_SetRenderDrawColor($render, |@rgb[$_], 255);
SDL_RenderDrawLine($render, |($x1, $y1, $x2, $y2)».round(1));
($x1, $y1) = $x2, $y2;
}
@rgb.=rotate($lines/60);
SDL_RenderPresent($render);
SDL_SetRenderDrawColor($render, 0, 0, 0, 0);
SDL_RenderClear($render);
}
SDL_Quit();
sub palette ($l) { (^$l).map: { hsv2rgb(($_ * 360/$l % 360)/360, 1, 1).list } };
sub hsv2rgb ( $h, $s, $v ){ # inputs normalized 0-1
my $c = $v * $s;
my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
my $m = $v - $c;
my ($r, $g, $b) = do given $h {
when 0..^(1/6) { $c, $x, 0 }
when 1/6..^(1/3) { $x, $c, 0 }
when 1/3..^(1/2) { 0, $c, $x }
when 1/2..^(2/3) { 0, $x, $c }
when 2/3..^(5/6) { $x, 0, $c }
when 5/6..1 { $c, 0, $x }
}
( $r, $g, $b ).map: ((*+$m) * 255).Int
}
Ring
# Project : Polyspiral
load "guilib.ring"
paint = null
incr = 1
x1 = 1000
y1 = 1080
angle = 10
length = 10
new qapp
{
win1 = new qwidget() {
setwindowtitle("")
setgeometry(10,10,1000,1080)
label1 = new qlabel(win1) {
setgeometry(10,10,1000,1080)
settext("")
}
new qpushbutton(win1) {
setgeometry(150,30,100,30)
settext("draw")
setclickevent("draw()")
}
show()
}
exec()
}
func draw
p1 = new qpicture()
color = new qcolor() {
setrgb(0,0,255,255)
}
pen = new qpen() {
setcolor(color)
setwidth(1)
}
paint = new qpainter() {
begin(p1)
setpen(pen)
for i = 1 to 150
x2 = x1 + cos(angle) * length
y2 = y1 + sin(angle) * length
drawline(x1, y1, x2, y2)
x1 = x2
y1 = y2
length = length + 3
angle = (angle + incr) % 360
next
endpaint()
}
label1 { setpicture(p1) show() }
Output:
https://www.dropbox.com/s/zwnpimbndekbd5k/PolySpiral.jpg?dl=0
Scala
Java Swing Interoperability
import java.awt._
import java.awt.event.ActionEvent
import javax.swing._
object PolySpiral extends App {
SwingUtilities.invokeLater(() =>
new JFrame("PolySpiral") {
class PolySpiral extends JPanel {
private var inc = 0.0
override def paintComponent(gg: Graphics): Unit = {
val g = gg.asInstanceOf[Graphics2D]
def drawSpiral(g: Graphics2D, l: Int, angleIncrement: Double): Unit = {
var len = l
var (x1, y1) = (getWidth / 2d, getHeight / 2d)
var angle = angleIncrement
for (i <- 0 until 150) {
g.setColor(Color.getHSBColor(i / 150f, 1.0f, 1.0f))
val x2 = x1 + math.cos(angle) * len
val y2 = y1 - math.sin(angle) * len
g.drawLine(x1.toInt, y1.toInt, x2.toInt, y2.toInt)
x1 = x2
y1 = y2
len += 3
angle = (angle + angleIncrement) % (math.Pi * 2)
}
}
super.paintComponent(gg)
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
drawSpiral(g, 5, math.toRadians(inc))
}
setBackground(Color.white)
setPreferredSize(new Dimension(640, 640))
new Timer(40, (_: ActionEvent) => {
inc = (inc + 0.05) % 360
repaint()
}).start()
}
add(new PolySpiral, BorderLayout.CENTER)
pack()
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
setLocationRelativeTo(null)
setResizable(true)
setVisible(true)
}
)
}
SPL
width,height = #.scrsize()
#.angle(#.degrees)
#.scroff()
incr = 0
>
incr = (incr+0.05)%360
x = width/2
y = height/2
length = 5
angle = incr
#.scrclear()
#.drawline(x,y,x,y)
> i, 1..150
x += length*#.cos(angle)
y += length*#.sin(angle)
#.drawcolor(#.hsv2rgb(angle,1,1):3)
#.drawline(x,y)
length += 3
angle = (angle+incr)%360
<
#.scr()
<
SVG
Demo: codepen
It's possible to render an animated polyspiral completely declaratively, using SVG/SMIL.
It requires building up layers, animated over a rotation transformation. This is verbose, so the code below has been truncated, and the demo uses another language (Pug) to generate the source.
<svg viewBox="0 0 100 100" stroke="#000" stroke-width="0.3">
<g>
<line x1="50" y1="50" x2="54" y2="50"></line>
<animateTransform attributeName="transform" type="rotate" from="-120 50 50" to="240 50 50" dur="2400s" repeatCount="indefinite"></animateTransform>
<g>
<line x1="54" y1="50" x2="58.16" y2="50"></line>
<animateTransform attributeName="transform" type="rotate" from="-120 54 50" to="240 54 50" dur="2400s" repeatCount="indefinite"></animateTransform>
<g>
<line x1="58.16" y1="50" x2="62.48639" y2="50"></line>
<animateTransform attributeName="transform" type="rotate" dur="2400s" repeatCount="indefinite" to="240 58.16 50" from="-120 58.16 50"></animateTransform>
<!-- ad nauseam -->
</g>
</g>
</g>
</svg>
Wren
import "graphics" for Canvas, Color
import "dome" for Window
import "math" for Math
var Radians = Fn.new { |d| d * Num.pi / 180 }
class Polyspiral {
construct new(width, height) {
Window.title = "Polyspiral"
Window.resize(width, height)
Canvas.resize(width, height)
_w = width
_h = height
_inc = 0
}
init() {
drawSpiral(5, Radians.call(_inc))
}
drawSpiral(length, angleIncrement) {
Canvas.cls(Color.white)
var x1 = _w / 2
var y1 = _h / 2
var len = length
var angle = angleIncrement
for (i in 0...150) {
var col = Color.hsv(i / 150 * 360, 1, 1)
var x2 = x1 + Math.cos(angle) * len
var y2 = y1 - Math.sin(angle) * len
Canvas.line(x1.truncate, y1.truncate, x2.truncate, y2.truncate, col)
x1 = x2
y1 = y2
len = len + 3
angle = (angle + angleIncrement) % (Num.pi * 2)
}
}
update() {
_inc = (_inc + 0.05) % 360
}
draw(alpha) {
drawSpiral(5, Radians.call(_inc))
}
}
var Game = Polyspiral.new(640, 640)
XPL0
There is no need for the MOD operator shown in the pseudo code for XPL0's trig functions because they handle argument angles outside 0 to 360 degrees (2 Pi radians).
def Width=640., Height=480.;
def Deg2Rad = 3.141592654/180.;
real Incr, Angle, Length, X, Y, X1, Y1;
int N;
[SetVid($101); \VESA 640x480x8 graphics
Incr:= 0.;
repeat Incr:= Incr+1.;
X:= Width/2.; Y:= Height/2.;
Move(fix(X), fix(Y));
Length:= 5.;
Angle:= Incr;
for N:= 1 to 150 do
[X1:= X + Length*Cos(Angle*Deg2Rad);
Y1:= Y + Length*Sin(Angle*Deg2Rad);
Line(fix(X1), fix(Y1), N+16);
X:= X1; Y:= Y1;
Length:= Length+3.;
Angle:= Angle+Incr;
];
DelayUS(83_333);
Clear;
until KeyHit;
]
- Output:
https://www.youtube.com/watch?v=p1M2VVY3abM The actual program looks better and runs under MS-DOS, Windows (with EXPL) and RPi.
Yabasic
w = 1024 : h = 600
open window w, h
color 255,0,0
incr = 0 : twopi = 2 * pi
while true
incr = mod(incr + 0.05, twopi)
x1 = w / 2
y1 = h / 2
length = 5
angle = incr
clear window
for i = 1 to 151
x2 = x1 + cos(angle) * length
y2 = y1 + sin(angle) * length
line x1, y1, x2, y2
x1 = x2 : y1 = y2
length = length + 3
angle = mod(angle + incr, twopi)
next
pause 1
end while
Zig
const std = @import("std");
const rl = @cImport({
@cInclude("raylib.h");
@cInclude("raymath.h");
});
const SCREEN_WIDTH = 640;
const SCREEN_HEIGHT = 480;
var incr: f32 = 0;
pub fn main() void {
rl.SetConfigFlags(rl.FLAG_WINDOW_RESIZABLE | rl.FLAG_VSYNC_HINT);
rl.SetTargetFPS(60);
rl.InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Polyspiral");
while (!rl.WindowShouldClose())
updateDrawFrame();
rl.CloseWindow();
}
fn updateDrawFrame() void {
rl.BeginDrawing();
rl.ClearBackground(rl.BLACK);
incr = @mod(incr + 0.001, 360);
drawSpiral(5, std.math.degreesToRadians(f32, incr));
rl.EndDrawing();
}
fn drawSpiral(_length: f32, _angle: f32) void {
const width = rl.GetScreenWidth();
const height = rl.GetScreenHeight();
var point0 = rl.Vector2{ .x = @as(f32, @floatFromInt(width)) / 2, .y = @as(f32, @floatFromInt(height)) / 2 };
var length = _length;
var angle = _angle;
for (0..150) |_| {
const line_vector = rl.Vector2Rotate(rl.Vector2{ .x = length, .y = 0 }, angle);
const point1 = rl.Vector2Add(point0, line_vector);
rl.DrawLineV(point0, point1, rl.LIME);
point0 = point1;
length += 3;
angle += incr;
angle = @mod(angle, comptime @as(f32, (2.0 * std.math.pi)));
}
}
zkl
![](http://static.miraheze.org/rosettacodewiki/thumb/2/2f/PolySprial.zkl.gif/250px-PolySprial.zkl.gif)
If you click on the image, it is animated.
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
w,h:=640,640;
bitmap:=PPM(w,h,0xFF|FF|FF); // White background
angleIncrement:=(3.0).toRad();
while(True){
r,angle:=0.0, 0.0;
ao,len,inc:=w/2, 2.5, angleIncrement+(130.0).toRad();
foreach c in (128){
s,a:=r + len, angle + inc;
x,y:=r.toRectangular(angle);
u,v:=r.toRectangular(a);
c=c.shiftLeft(21) + c.shiftLeft(10) + c*8; // convert c to a RGB
bitmap.line(ao+x,ao+y, ao+u,ao+v, c);
r,angle=s,a;
}
bitmap.writeJPGFile("polyspiral.zkl.jpg");
bitmap.fill(0xFF|FF|FF); // White background
angleIncrement=(angleIncrement + 0.05);
Atomic.sleep(3);
}
- Programming Tasks
- Solutions by Programming Task
- Action!
- Action! Tool Kit
- Action! Real Math
- AutoHotkey
- C
- C sharp
- C++
- Ceylon
- Delphi
- SysUtils,StdCtrls
- EasyLang
- FreeBASIC
- FutureBasic
- Fōrmulæ
- Gnuplot
- Pages with broken file links
- Go
- Haskell
- IS-BASIC
- J
- Java
- JavaScript
- Julia
- Kotlin
- Lua
- LÖVE
- Mathematica
- Wolfram Language
- Nim
- Gintro
- PARI/GP
- Perl
- Phix
- Phix/pGUI
- Phix/online
- Processing
- Python
- Pygame
- Quackery
- Racket
- Raku
- Ring
- Scala
- SPL
- SVG
- Wren
- DOME
- XPL0
- Yabasic
- Zig
- Raylib
- Zkl