Sunflower fractal
Draw a Sunflower fractal
11l
-V
phi = (1 + sqrt(5)) / 2
size = 600
seeds = 5 * size
print(‘<svg xmlns="http://www.w3.org/2000/svg" width="’size‘" height="’size‘" style="stroke:gold">’)
print(‘<rect width="100%" height="100%" fill="black" />’)
L(i) 1..seeds
V r = 2 * (i ^ phi) / seeds
V t = 2 * math:pi * phi * i
print(‘<circle cx="#.2" cy="#.2" r="#.1" />’.format(r * sin(t) + size / 2,
r * cos(t) + size / 2, sqrt(i) / 13))
print(‘</svg>’)
Action!
Calculations on a real Atari 8-bit computer take quite long time. It is recommended to use an emulator capable with increasing speed of Atari CPU.
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 Circle(INT x0,y0,d)
BYTE MaxD=[13]
BYTE ARRAY Start=[0 1 2 4 6 9 12 16 20 25 30 36 42 49]
BYTE ARRAY MaxY=[0 0 1 1 2 2 3 3 4 4 5 5 6 6]
INT ARRAY CircleX=[
0 0 1 0 1 1 2 1 0 2 2 1 3 2 2 0 3 3 2 1
4 4 3 2 1 4 4 4 3 2 5 5 4 4 3 1 5 5 5 4 4 2
6 6 5 5 4 3 1 6 6 6 5 5 4 2]
INT i,ind,max
CARD x
BYTE dx,y
IF d>MAXD THEN d=MaxD FI
IF d<0 THEN d=0 FI
ind=Start(d)
max=MaxY(d)
FOR i=0 TO max
DO
dx=CircleX(ind)
y=y0-i
IF (y>=0) AND (y<=191) THEN
Plot(x0-dx,y) DrawTo(x0+dx,y)
FI
y=y0+i
IF (y>=0) AND (y<=191) THEN
Plot(x0-dx,y) DrawTo(x0+dx,y)
FI
ind==+1
OD
RETURN
PROC DrawFractal(CARD seeds INT x0,y0)
CARD i
REAL a,c,r,ir,tmp,tmp2,r256,rx,ry,rr,r360,c360,seeds2
INT ia,sc,x,y
IntToReal(256,r256)
ValR("1.618034",c) ;c=(sqrt(5)+1)/2
IntToReal(seeds/2,seeds2) ;seeds2=seeds/2
IntToReal(360,r360)
RealMult(r360,c,c360) ;c360=360*c
FOR i=0 TO seeds
DO
IntToReal(i,ir)
Power(ir,c,tmp)
RealDiv(tmp,seeds2,r) ;r=i^c/(seeds/2)
RealMult(c360,ir,a) ;a=360*c*i
WHILE RealGreaterOrEqual(a,r360)
DO
RealSub(a,r360,tmp)
RealAssign(tmp,a)
OD
ia=RealToInt(a)
sc=Sin(ia)
IntToRealForNeg(sc,tmp)
RealDiv(tmp,r256,tmp2)
RealMult(r,tmp2,rx)
x=Round(rx) ;x=r*sin(a)
sc=Cos(ia)
IntToRealForNeg(sc,tmp)
RealDiv(tmp,r256,tmp2)
RealMult(r,tmp2,ry)
y=Round(ry) ;y=r*cos(a)
Circle(x+x0,y+y0,10*i/seeds)
Poke(77,0) ;turn off the attract mode
OD
RETURN
PROC Main()
BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6
Graphics(8+16)
Color=1
COLOR1=$12
COLOR2=$18
DrawFractal(1000,160,96)
DO UNTIL CH#$FF OD
CH=$FF
RETURN
- Output:
Screenshot from Atari 8-bit computer
Applesoft BASIC
HGR:A=PEEK(49234):C=(SQR(5)+1)/2:N=900:FORI=0TO1600:R=(I^C)/N:A=8*ATN(1)*C*I:X=R*SIN(A)+139:Y=R*COS(A)+96:F=7-4*((X-INT(X/2)*2)>=.75):X=(X>=0ANDX<280)*X:Y=(Y>=0ANDY<192)*Y:HCOLOR=F*(XANDY):HPLOTX,Y:NEXT
C
The colouring of the "fractal" is determined with every iteration to ensure that the resulting graphic looks similar to a real Sunflower, thus the parameter diskRatio determines the radius of the central disk as the maximum radius of the flower is known from the number of iterations. The scaling factor is currently hardcoded but can also be externalized. Requires the WinBGIm library.
/*Abhishek Ghosh, 14th September 2018*/
#include<graphics.h>
#include<math.h>
#define pi M_PI
void sunflower(int winWidth, int winHeight, double diskRatio, int iter){
double factor = .5 + sqrt(1.25),r,theta;
double x = winWidth/2.0, y = winHeight/2.0;
double maxRad = pow(iter,factor)/iter;
int i;
setbkcolor(LIGHTBLUE);
for(i=0;i<=iter;i++){
r = pow(i,factor)/iter;
r/maxRad < diskRatio?setcolor(BLACK):setcolor(YELLOW);
theta = 2*pi*factor*i;
circle(x + r*sin(theta), y + r*cos(theta), 10 * i/(1.0*iter));
}
}
int main()
{
initwindow(1000,1000,"Sunflower...");
sunflower(1000,1000,0.5,3000);
getch();
closegraph();
return 0;
}
C++
#include <cmath>
#include <fstream>
#include <iostream>
bool sunflower(const char* filename) {
std::ofstream out(filename);
if (!out)
return false;
constexpr int size = 600;
constexpr int seeds = 5 * size;
constexpr double pi = 3.14159265359;
constexpr double phi = 1.61803398875;
out << "<svg xmlns='http://www.w3.org/2000/svg\' width='" << size;
out << "' height='" << size << "' style='stroke:gold'>\n";
out << "<rect width='100%' height='100%' fill='black'/>\n";
out << std::setprecision(2) << std::fixed;
for (int i = 1; i <= seeds; ++i) {
double r = 2 * std::pow(i, phi)/seeds;
double theta = 2 * pi * phi * i;
double x = r * std::sin(theta) + size/2;
double y = r * std::cos(theta) + size/2;
double radius = std::sqrt(i)/13;
out << "<circle cx='" << x << "' cy='" << y << "' r='" << radius << "'/>\n";
}
out << "</svg>\n";
return true;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cerr << "usage: " << argv[0] << " filename\n";
return EXIT_FAILURE;
}
if (!sunflower(argv[1])) {
std::cerr << "image generation failed\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
- Output:
FreeBASIC
Const PI As Double = 4 * Atn(1)
Const ancho = 400
Const alto = 400
Screenres ancho, alto, 8
Windowtitle" Pulsa una tecla para finalizar"
Cls
Sub Sunflower(semillas As Integer)
Dim As Double c = (Sqr(5)+1)/2
For i As Integer = 0 To semillas
Dim As Double r = (i^c) / semillas
Dim As Double angulo = 2 * Pi * c * i
Dim As Double x = r * Sin(angulo) + 200
Dim As Double y = r * Cos(angulo) + 200
Circle (x, y), i/semillas*10, i/semillas*10
Next i
End Sub
Sunflower(2000)
Bsave "sunflower_fractal.bmp",0
Sleep
End
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
The method consists in drawing points on a spriral, an archimedean spiral, where two contiguous points are separated (in angle) by the golden angle.
Because the points tend to agglomerate in the center, they are smaller there.
Improvement
Last result is not natural. Florets in a sunflower are all equal size.
H. Vogel proposed to use a Fermat spiral, in such a case, the florets are equally spaced, and we can use now circles with the same size:
FutureBasic
window 1, @"Sunflower Fractal", ( 0, 0, 400, 400 )
WindowSetBackgroundColor( 1, fn ColorBlack )
void local fn SunflowerFractal
NSUinteger seeds = 4000
double c, i, angle, x, y, r
pen 2.0, fn ColorWithRGB( 0.997, 0.838, 0.038, 1.0 )
c = ( sqr(5) + 1 ) / 2
for i = 0 to seeds
r = (i ^ c) / seeds
angle = 2 * pi * c * i
x = r * sin(angle) + 200
y = r * cos(angle) + 200
oval ( x, y, i / seeds * 5, i / seeds * 5 )
next
end fn
fn SunflowerFractal
HandleEvents
Go
The image produced, when viewed with (for example) EOG, is similar to the Ring entry.
package main
import (
"github.com/fogleman/gg"
"math"
)
func main() {
dc := gg.NewContext(400, 400)
dc.SetRGB(1, 1, 1)
dc.Clear()
dc.SetRGB(0, 0, 1)
c := (math.Sqrt(5) + 1) / 2
numberOfSeeds := 3000
for i := 0; i <= numberOfSeeds; i++ {
fi := float64(i)
fn := float64(numberOfSeeds)
r := math.Pow(fi, c) / fn
angle := 2 * math.Pi * c * fi
x := r*math.Sin(angle) + 200
y := r*math.Cos(angle) + 200
fi /= fn / 5
dc.DrawCircle(x, y, fi)
}
dc.SetLineWidth(1)
dc.Stroke()
dc.SavePNG("sunflower_fractal.png")
}
JavaScript
HTML to test
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Sunflower</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body{background-color:black;text-align:center;margin-top:150px} </style> <script src="sunflower.js"></script> </head> <body onload="start()"> <div id='wnd'></div> </body> </html>
const SIZE = 400, HS = SIZE >> 1, WAIT = .005, SEEDS = 3000,
TPI = Math.PI * 2, C = (Math.sqrt(10) + 1) / 2;
class Sunflower {
constructor() {
this.wait = WAIT;
this.colorIndex = 0;
this.dimension = 0;
this.lastTime = 0;
this.accumulator = 0;
this.deltaTime = 1 / 60;
this.colors = ["#ff0000", "#ff8000", "#ffff00", "#80ff00", "#00ff00", "#00ff80",
"#00ffff", "#0080ff", "#0000ff", "#8000ff", "#ff00ff", "#ff0080"];
this.canvas = document.createElement('canvas');
this.canvas.width = SIZE;
this.canvas.height = SIZE;
const d = document.getElementById("wnd");
d.appendChild(this.canvas);
this.ctx = this.canvas.getContext('2d');
}
draw(clr, d) {
let r = Math.pow(d, C) / SEEDS;
let angle = TPI * C * d;
let x = HS + r * Math.sin(angle),
y = HS + r * Math.cos(angle);
this.ctx.strokeStyle = clr;
this.ctx.beginPath();
this.ctx.arc(x, y, d / (SEEDS / 50), 0, TPI);
this.ctx.closePath();
this.ctx.stroke();
}
update(dt) {
if((this.wait -= dt) < 0) {
this.draw(this.colors[this.colorIndex], this.dimension);
this.wait = WAIT;
if((this.dimension++) > 600) {
this.dimension = 0;
this.colorIndex = (this.colorIndex + 1) % this.colors.length;
}
}
}
start() {
this.loop = (time) => {
this.accumulator += (time - this.lastTime) / 1000;
while(this.accumulator > this.deltaTime) {
this.accumulator -= this.deltaTime;
this.update(Math.min(this.deltaTime));
}
this.lastTime = time;
requestAnimationFrame(this.loop);
}
this.loop(0);
}
}
function start() {
const sunflower = new Sunflower();
sunflower.start();
}
J
This (currently draft) task really needs an adequate description. Still, it's straightforward to derive code from another implementation on this page.
This implementation assumes a recent J implementation (for example, J903):
require'format/printf'
sunfract=: {{ NB. y: number of "sunflower seeds"
phi=. 0.5*1+%:5
XY=. (y%10)+(2*(I^phi)%y) * +.^j.2*1p1*phi*I=.1+i.y
XY,.(%:I)%13
}}
sunfractsvg=: {{
fract=. sunfract x
C=.,'\n<circle cx="%.2f" cy="%.2f" r="%.1f" />' sprintf fract
({{)n
<svg xmlns="http://www.w3.org/2000/svg" width="%d" height="%d" style="stroke:gold">
<rect width="100%%" height="100%%" fill="black" />
%s
</svg>
}} sprintf (;/<.20+}:>./fract),<C) fwrite y}}
Example use:
3000 sunfractsvg '~/sunfract.html'
129147
(The number displayed is the size of the generated file.)
jq
Adapted from Perl
Works with gojq, the Go implementation of jq
# SVG headers
def svg(size):
"<svg xmlns='http://www.w3.org/2000/svg' width='\(size)'",
"height='\(size)' style='stroke:gold'>",
"<rect width='100%' height='100%' fill='black'/>";
# emit the "<circle />" elements
def sunflower(size):
def rnd: 100*.|round/100;
(5 * size) as $seeds
| ((1|atan) * 4) as $pi
| ((1 + (5|sqrt)) / 2) as $phi
| range(1; 1 + $seeds) as $i
| {}
| .r = 2 * pow($i; $phi)/$seeds
| .theta = 2 * $pi * $phi * $i
| .x = .r * (.theta|sin) + size/2
| .y = .r * (.theta|cos) + size/2
| .radius = ($i|sqrt)/13
| "<circle cx='\(.x|rnd)' cy='\(.y|rnd)' r='\(.radius|rnd)' />" ;
def end_svg:
"</svg>";
svg(600),
sunflower(600),
end_svg
Julia
Run from REPL.
using GLMakie
function sunflowerplot()
len = 2000
ϕ = 0.5 + sqrt(5) / 2
r = LinRange(0.0, 100.0, len)
θ = zeros(len)
markersizes = zeros(Int, len)
for i in 2:length(r)
θ[i] = θ[i - 1] + 2π * ϕ
markersizes[i] = div(i, 500) + 9
end
x = r .* cos.(θ)
y = r .* sin.(θ)
f = Figure()
ax = Axis(f[1, 1], backgroundcolor = :green)
scatter!(ax, x, y, color = :gold, markersize = markersizes, strokewidth = 1)
hidespines!(ax)
hidedecorations!(ax)
return f
end
sunflowerplot()
- Output:
Liberty BASIC
nomainwin
UpperLeftX=1:UpperLeftY=1
WindowWidth=800:WindowHeight=600
open "Sunflower Fractal" for graphics_nf_nsb as #1
#1 "trapclose [q];down;fill darkred;flush;size 3"
c=1.618033988749895
seeds=8000
rd=gn=bl=int(rnd(1)*255)
for i=0 to seeds
rd=rd+5:if rd>254 then rd=1
gn=gn+3:if gn>254 then gn=1
bl=bl+1:if bl>254 then bl=1
#1 "color ";rd;" ";gn;" ";bl
#1 "backcolor ";rd;" ";gn;" ";bl
r=(i^c)/seeds
angle=2*3.14159*c*i
x=r*sin(angle)+400
y=r*cos(angle)+280
#1 "place ";x;" ";y
#1 "circlefilled ";i/seeds*5
scan
next i
wait
[q]
close #1
end
Mathematica / Wolfram Language
numseeds = 3000;
pts = Table[
i = N[ni];
r = i^GoldenRatio/numseeds;
t = 2 Pi GoldenRatio i;
Circle[AngleVector[{r, t}], i/(numseeds/3)]
,
{ni, numseeds}
];
Graphics[pts]
Microsoft Small Basic
' Sunflower fractal - 24/07/2018
GraphicsWindow.Width=410
GraphicsWindow.Height=400
c=(Math.SquareRoot(5)+1)/2
numberofseeds=3000
For i=0 To numberofseeds
r=Math.Power(i,c)/numberofseeds
angle=2*Math.Pi*c*i
x=r*Math.Sin(angle)+200
y=r*Math.Cos(angle)+200
GraphicsWindow.DrawEllipse(x, y, i/numberofseeds*10, i/numberofseeds*10)
EndFor
- Output:
Nim
import math
import imageman
const
Size = 600
Background = ColorRGBU [byte 0, 0, 0]
Foreground = ColorRGBU [byte 0, 255, 0]
C = (sqrt(5.0) + 1) / 2
NumberOfSeeds = 6000
Fn = float(NumberOfSeeds)
var image = initImage[ColorRGBU](Size, Size)
image.fill(Background)
for i in 0..<NumberOfSeeds:
let
fi = float(i)
r = pow(fi, C) / Fn
angle = 2 * PI * C * fi
x = toInt(r * sin(angle) + Size div 2)
y = toInt(r * cos(angle) + Size div 2)
image.drawCircle(x, y, toInt(8 * fi / Fn), Foreground)
image.savePNG("sunflower.png", compression = 9)
Objeck
use Game.SDL2;
use Game.Framework;
class Test {
@framework : GameFramework;
@colors : Color[];
function : Main(args : String[]) ~ Nil {
Test->New()->Run();
}
New() {
@framework := GameFramework->New(GameConsts->SCREEN_WIDTH, GameConsts->SCREEN_HEIGHT, "Test");
@framework->SetClearColor(Color->New(0, 0, 0));
@colors := Color->New[2];
@colors[0] := Color->New(255,128,0);
@colors[1] := Color->New(255,255,25);
}
method : Run() ~ Nil {
if(@framework->IsOk()) {
e := @framework->GetEvent();
quit := false;
while(<>quit) {
# process input
while(e->Poll() <> 0) {
if(e->GetType() = EventType->SDL_QUIT) {
quit := true;
};
};
@framework->FrameStart();
Render(525,525,0.50,3000);
@framework->FrameEnd();
};
}
else {
"--- Error Initializing Environment ---"->ErrorLine();
return;
};
leaving {
@framework->Quit();
};
}
method : Render(winWidth : Int, winHeight : Int, diskRatio : Float, iter : Int) ~ Nil {
renderer := @framework->GetRenderer();
@framework->Clear();
factor := 0.5 + 1.25->SquareRoot();
x := winWidth / 2.0;
y := winHeight / 2.0;
maxRad := Float->Power(iter, factor) / iter;
for(i:=0;i<=iter;i+=1;) {
r := Float->Power(i,factor)/iter;
color := r/maxRad < diskRatio ? @colors[0] : @colors[1];
theta := 2*Float->Pi()*factor*i;
renderer->CircleColor(x + r*theta->Sin(), y + r*theta->Cos(), 10 * i/(1.0*iter), color);
};
@framework->Show();
}
}
consts GameConsts {
SCREEN_WIDTH := 640,
SCREEN_HEIGHT := 480
}
Perl
use utf8;
use constant π => 3.14159265;
use constant φ => (1 + sqrt(5)) / 2;
my $scale = 600;
my $seeds = 5*$scale;
print qq{<svg xmlns="http://www.w3.org/2000/svg" width="$scale" height="$scale" style="stroke:gold">
<rect width="100%" height="100%" fill="black" />\n};
for $i (1..$seeds) {
$r = 2 * ($i**φ) / $seeds;
$t = 2 * π * φ * $i;
$x = $r * sin($t) + $scale/2;
$y = $r * cos($t) + $scale/2;
printf qq{<circle cx="%.2f" cy="%.2f" r="%.1f" />\n}, $x, $y, sqrt($i)/13;
}
print "</svg>\n";
See Phi-packing image (SVG image)
Phix
You can run this online here.
with javascript_semantics constant numberofseeds = 3000 include pGUI.e Ihandle dlg, canvas cdCanvas cddbuffer, cdcanvas function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/) integer {hw, hh} = sq_floor_div(IupGetIntInt(canvas, "DRAWSIZE"),2) atom s = min(hw,hh)/150, f = min(hw,hh)*8/125 cdCanvasActivate(cddbuffer) cdCanvasClear(cddbuffer) atom c = (sqrt(5)+1)/2 for i=0 to numberofseeds do atom r = power(i,c)/numberofseeds, angle = 2*PI*c*i, x = s*r*sin(angle)+hw, y = s*r*cos(angle)+hh cdCanvasCircle(cddbuffer,x,y,i/numberofseeds*f) end for cdCanvasFlush(cddbuffer) return IUP_DEFAULT end function function map_cb(Ihandle ih) cdcanvas = cdCreateCanvas(CD_IUP, ih) cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas) cdCanvasSetBackground(cddbuffer, CD_WHITE) cdCanvasSetForeground(cddbuffer, CD_BLACK) return IUP_DEFAULT end function procedure main() IupOpen() canvas = IupCanvas(NULL) IupSetAttribute(canvas, "RASTERSIZE", "602x502") -- initial size IupSetCallback(canvas, "MAP_CB", Icallback("map_cb")) dlg = IupDialog(canvas) IupSetAttribute(dlg, "TITLE", "Sunflower") IupSetCallback(canvas, "ACTION", Icallback("redraw_cb")) IupShow(dlg) IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation if platform()!=JS then IupMainLoop() IupClose() end if end procedure main()
Processing
//Abhishek Ghosh, 26th June 2022
size(1000,1000);
surface.setTitle("Sunflower...");
int iter = 3000;
float factor = .5 + sqrt(1.25),r,theta,diskRatio=0.5;
float x = width/2.0, y = height/2.0;
double maxRad = pow(iter,factor)/iter;
int i;
background(#add8e6); //Lightblue background
for(i=0;i<=iter;i++){
r = pow(i,factor)/iter;
if(r/maxRad < diskRatio){
stroke(#000000); // Black central disk
}
else
stroke(#ffff00); // Yellow Petals
theta = 2*PI*factor*i;
ellipse(x + r*sin(theta), y + r*cos(theta), 10 * i/(1.0*iter),10 * i/(1.0*iter));
}
Python
from turtle import *
from math import *
# Based on C implementation
iter = 3000
diskRatio = .5
factor = .5 + sqrt(1.25)
screen = getscreen()
(winWidth, winHeight) = screen.screensize()
#x = winWidth/2.0
#y = winHeight/2.0
x = 0.0
y = 0.0
maxRad = pow(iter,factor)/iter;
bgcolor("light blue")
hideturtle()
tracer(0, 0)
for i in range(iter+1):
r = pow(i,factor)/iter;
if r/maxRad < diskRatio:
pencolor("black")
else:
pencolor("yellow")
theta = 2*pi*factor*i;
up()
setposition(x + r*sin(theta), y + r*cos(theta))
down()
circle(10.0 * i/(1.0*iter))
update()
done()
R
phi=1/2+sqrt(5)/2
r=seq(0,1,length.out=2000)
theta=numeric(length(r))
theta[1]=0
for(i in 2:length(r)){
theta[i]=theta[i-1]+phi*2*pi
}
x=r*cos(theta)
y=r*sin(theta)
par(bg="black")
plot(x,y)
size=seq(.5,2,length.out = length(x))
thick=seq(.1,2,length.out = length(x))
for(i in 1:length(x)){
points(x[i],y[i],cex=size[i],lwd=thick[i],col="goldenrod1")
}
- Output:
Racket
#lang racket
(require 2htdp/image)
(define N 3000)
(define DISK-RATIO 0.5)
(define factor (+ 0.5 (sqrt 1.25)))
(define WIDTH 500)
(define HEIGHT 500)
(define max-rad (/ (expt N factor) N))
(for/fold ([image (empty-scene WIDTH HEIGHT)]) ([i (in-range N)])
(define r (/ (expt i factor) N))
(define color (if (< (/ r max-rad) DISK-RATIO) 'brown 'darkyellow))
(define theta (* 2 pi factor i))
(place-image (circle (* 10 i (/ 1 N)) 'outline color)
(+ (/ WIDTH 2) (* r (sin theta)))
(+ (/ HEIGHT 2) (* r (cos theta)))
image))
Raku
(formerly Perl 6)
This is not really a fractal. It is more accurately an example of a Fibonacci spiral or Phi-packing.
Or, to be completely accurate: It is a variation of a generative Fermat's spiral using the Vogel model to implement phi-packing. See: https://thatsmaths.com/2014/06/05/sunflowers-and-fibonacci-models-of-efficiency
use SVG;
my $seeds = 3000;
my @center = 300, 300;
my $scale = 5;
constant \φ = (3 - 5.sqrt) / 2;
my @c = map {
my ($x, $y) = ($scale * .sqrt) «*« |cis($_ * φ * τ).reals »+« @center;
[ $x.round(.01), $y.round(.01), (.sqrt * $scale / 100).round(.1) ]
}, 1 .. $seeds;
say SVG.serialize(
svg => [
:600width, :600height, :style<stroke:yellow>,
:rect[:width<100%>, :height<100%>, :fill<black>],
|@c.map( { :circle[:cx(.[0]), :cy(.[1]), :r(.[2])] } ),
],
);
See: Phi packing (SVG image)
Ring
# Project : Sunflower fractal
load "guilib.ring"
paint = null
new qapp
{
win1 = new qwidget() {
setwindowtitle("Sunflower fractal")
setgeometry(100,100,320,500)
label1 = new qlabel(win1) {
setgeometry(10,10,400,400)
settext("")
}
new qpushbutton(win1) {
setgeometry(100,400,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)
c = (sqrt(5) + 1) / 2
numberofseeds = 3000
for i = 0 to numberofseeds
r = pow(i, c ) / (numberofseeds)
angle = 2 * 3.14 * c * i
x = r * sin(angle) + 100
y = r * cos(angle) + 100
drawellipse(x, y, i / (numberofseeds / 10), i / (numberofseeds / 10))
next
endpaint()
}
label1 { setpicture(p1) show() }
Output:
Sidef
require('Imager')
func draw_sunflower(seeds=3000) {
var img = %O<Imager>.new(
xsize => 400,
ysize => 400,
)
var c = (sqrt(1.25) + 0.5)
{ |i|
var r = (i**c / seeds)
var θ = (2 * Num.pi * c * i)
var x = (r * sin(θ) + 200)
var y = (r * cos(θ) + 200)
img.circle(x => x, y => y, r => i/(5*seeds))
} * seeds
return img
}
var img = draw_sunflower()
img.write(file => "sunflower.png")
Output image: Sunflower fractal
V (Vlang)
import gg
import gx
import math
fn main() {
mut context := gg.new_context(
bg_color: gx.rgb(255, 255, 255)
width: 400
height: 400
frame_fn: frame
)
context.run()
}
fn frame(mut ctx gg.Context) {
ctx.begin()
c := (math.sqrt(5) + 1) / 2
num_of_seeds := 3000
for i := 0; i <= num_of_seeds; i++ {
mut fi := f64(i)
n := f64(num_of_seeds)
r := math.pow(fi, c) / n
angle := 2 * math.pi * c * fi
x := r*math.sin(angle) + 200
y := r*math.cos(angle) + 200
fi /= n / 5
ctx.draw_circle_filled(f32(x), f32(y), f32(fi), gx.black)
}
ctx.end()
}
Wren
import "graphics" for Canvas, Color
import "dome" for Window
class Game {
static init() {
Window.title = "Sunflower fractal"
var width = 400
var height = 400
Window.resize(width, height)
Canvas.resize(width, height)
Canvas.cls(Color.black)
var col = Color.green
var seeds = 3000
sunflower(seeds, col)
}
static update() {}
static draw(alpha) {}
static sunflower(seeds, col) {
var c = (5.sqrt + 1) / 2
for (i in 0..seeds) {
var r = i.pow(c) / seeds
var angle = 2 * Num.pi * c * i
var x = r*angle.sin + 200
var y = r*angle.cos + 200
Canvas.circle(x, y, i/seeds*5, col)
}
}
}
XPL0
proc DrawCircle(X0, Y0, R, Color);
int X0, Y0, R, Color;
int X, Y, R2;
[R2:= R*R;
for Y:= -R to +R do
for X:= -R to +R do
if X*X + Y*Y <= R2 then
Point(X+X0, Y+Y0, Color);
];
def Seeds = 3000, Color = $0E; \yellow
def ScrW = 800, ScrH = 600;
def Phi = (sqrt(5.)+1.) / 2.; \golden ratio (1.618...)
def Pi = 3.14159265358979323846;
real R, Angle, X, Y;
int I;
[SetVid($103);
for I:= 0 to Seeds-1 do
[R:= Pow(float(I), Phi) / float(Seeds/2);
Angle:= 2. * Pi * Phi * float(I);
X:= R*Sin(Angle);
Y:= R*Cos(Angle);
DrawCircle(ScrW/2+fix(X), ScrH/2-fix(Y), I*7/Seeds, Color);
];
]
Yabasic
// Rosetta Code problem: http://rosettacode.org/wiki/Sunflower_fractal
// Adapted from Wren to Yabasic by Galileo, 01/2022
width = 400
height = 400
open window width, height
backcolor 0,0,0
clear window
color 0,255,0
seeds = 3000
c = (sqrt(5) + 1) / 2
for i = 0 to seeds
r = (i ** c) / seeds
angle = 2 * pi * c * i
x = r * sin(angle) + 200
y = r * cos(angle) + 200
circle x, y, i / seeds * 5
next
zkl
Uses Image Magick and the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
fcn sunflower(seeds=3000){
img,color := PPM(400,400), 0x00ff00; // green
c:=((5.0).sqrt() + 1)/2;
foreach n in ([0.0 .. seeds]){ // floats
r:=n.pow(c)/seeds;
x,y := r.toRectangular(r.pi*c*n*2);
r=(n/seeds*5).toInt();
img.circle(200 + x, 200 + y, r,color);
}
img.writeJPGFile("sunflower.zkl.jpg");
}();
- Output:
Image at sunflower fractal
- Draft Programming Tasks
- Clarify task
- 11l
- Action!
- Action! Tool Kit
- Action! Real Math
- Applesoft BASIC
- C
- C++
- FreeBASIC
- Fōrmulæ
- FutureBasic
- Pages with broken file links
- Go
- Go Graphics
- JavaScript
- J
- Jq
- Julia
- Liberty BASIC
- Mathematica
- Wolfram Language
- Microsoft Small Basic
- Nim
- Imageman
- Objeck
- Perl
- Phix
- Phix/pGUI
- Phix/online
- Processing
- Python
- R
- Racket
- Raku
- Ring
- Sidef
- V (Vlang)
- Wren
- DOME
- XPL0
- Yabasic
- Zkl