Barnsley fern: Difference between revisions

(11 intermediate revisions by 8 users not shown)
Line 368:
NEXT
END</syntaxhighlight>
==={{header|uBasic/4tH}}===
uBasic/4tH does not feature graphics or floating point, so it requires some extra code to achieve this. This version uses binary scaling.
<syntaxhighlight lang="qbasic">Dim @o(5) ' 0 = SVG file, 1 = color, 2 = fillcolor, 3 = pixel, 4 = text
 
' === Begin Program ===
 
If Info("wordsize") < 64 Then Print "This program requires a 64-bit uBasic" : End
 
Proc _SVGopen ("svgfern.svg")
Proc _Canvas (500, 768) ' light gray background
Proc _Background (FUNC(_RGBtoColor (0, 0, 0)))
Proc _SetMode ("dot") ' we want dots, not pixels
 
For i = 1 To 25000
Let r = Rnd (100)
 
If r = 1 Then
Let x = 0
Let y = FUNC (_Fmul(FUNC(_Fdiv(16, 100)) , y))
Else
 
If r < 9 Then
Let x = FUNC(_Fmul(FUNC(_Fdiv(2, 10)), x)) - FUNC(_Fmul(FUNC(_Fdiv(26, 100)), y))
Let y = FUNC(_Fmul(FUNC(_Fdiv(-23, 100)), x)) + FUNC(_Fmul(FUNC(_Fdiv(22, 100)), y)) + FUNC(_Fdiv(16, 10))
Else
 
If r < 16 then
Let x = FUNC(_Fmul(FUNC(_Fdiv(-15, 100)), x)) + FUNC(_Fmul(FUNC(_Fdiv(28, 100)), y))
Let y = FUNC(_Fmul(FUNC(_Fdiv(26, 100)), x)) + FUNC(_Fmul(FUNC(_Fdiv(24, 100)), y)) + FUNC(_Fdiv(44, 100))
Else
 
Let x = FUNC(_Fmul(FUNC(_Fdiv(85, 100)), x)) + FUNC(_Fmul(FUNC(_Fdiv(4, 100)), y))
Let y = FUNC(_Fmul(FUNC(_Fdiv(-4, 100)), x)) + FUNC(_Fmul(FUNC(_Fdiv(85, 100)), y)) + FUNC(_Fdiv(16, 10))
EndIf
EndIf
EndIf
 
Let q = FUNC(_Fround(FUNC(_Fmul(x + FUNC(_Ntof(3)), FUNC(_Ntof(70))))))
Let p = FUNC(_Fround(FUNC(_Ntof(700)) - FUNC(_Fmul(y, FUNC(_Ntof(70))))))
 
Proc _SetColor (FUNC(_RGBtoColor (0, 128 + Rnd(128), 0)))
Proc _SetPixel (p+20, q)
Next
 
Proc _SVGclose
End
 
' === End Program ===
 
_Ntof Param (1) : Return (a@*16384)
_Ftoi Param (1) : Return ((10000*a@)/16384)
_Fmul Param (2) : Return ((a@*b@)/16384)
_Fdiv Param (2) : Return ((a@*16384)/b@)
_Fround Param (1) : Return ((a@+8192)/16384)
 
_RGBtoColor Param (3) : Return (a@ * 65536 + b@ * 256 + c@)
_SetColor Param (1) : @o(1) = a@ : Return
_GetColor Return (@o(1))
_SetFill Param (1) : @o(2) = a@ : Return
_GetFill Return (@o(2))
_SetPixel Param(2) : Proc @o(3)(a@, b@) : Return
_SVGclose Write @o(0), "</svg>" : Close @o(0) : Return
_color_ Param (1) : Proc _PrintRGB (a@) : Write @o(0), "\q />" : Return
 
_PrintRGB
Param (1)
Radix 16
 
If a@ < 0 Then
Write @o(0), "none";
Else
Write @o(0), Show(Str ("#!######", a@));
EndIf
 
Radix 10
Return
 
_Background
Param (1)
 
Write @o(0), "<rect width=\q100%\q height=\q100%\q fill=\q";
Proc _color_ (a@)
Return
 
_pixel_
Param (2)
 
Write @o(0), "<rect x=\q";b@;"\q y=\q";a@;
Write @o(0), "\q width=\q1px\q height=\q1px\q fill=\q";
Proc _color_ (@o(1))
Return
 
_dot_
Param (2)
 
Write @o(0), "<circle cx=\q";b@;"\q cy=\q";a@;
Write @o(0), "\q r=\q0.5px\q fill=\q";
Proc _color_ (@o(1))
Return
 
_SetMode
Param (1)
 
If Comp(a@, "pixel") = 0 Then
@o(3) = _pixel_
Else If Comp(a@, "dot") = 0 Then
@o(3) = _dot_
Else Print "Bad mode" : Raise 1
Endif : Endif
Return
 
_Canvas
Param (2)
 
Write @o(0), "<svg width=\q";a@;"\q height=\q";b@;"\q viewBox=\q0 0 ";a@;" ";b@;
Write @o(0), "\q xmlns=\qhttp://www.w3.org/2000/svg\q ";
Write @o(0), "xmlns:xlink=\qhttp://www.w3.org/1999/xlink\q>"
Return
 
_SVGopen
Param (1)
 
If Set (@o(0), Open (a@, "w")) < 0 Then
Print "Cannot open \q";Show (a@);"\q" : Raise 1
Else
Write @o(0), "<?xml version=\q1.0\q encoding=\qUTF-8\q standalone=\qno\q?>"
Write @o(0), "<!DOCTYPE svg PUBLIC \q-//W3C//DTD SVG 1.1//EN\q ";
Write @o(0), "\qhttp://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\q>"
EndIf
Return</syntaxhighlight>
This version uses decimal fixed-point numbers. It is not only faster, but also provides a better rendition of the Barnsley fern. It uses the very same SVG routines as the version above, so these are not included.
{{Trans|Forth}}
<syntaxhighlight lang="qbasic">Dim @o(5) ' 0 = SVG file, 1 = color, 2 = fillcolor, 3 = pixel, 4 = text
Dim @c(20) ' coefficients
 
w = 400 : h = 600 : s = 17
 
Proc _coefficients
Proc _SVGopen ("svgfern.svg")
Proc _Canvas (w, h) ' light gray background
Proc _Background (FUNC(_RGBtoColor (0, 0, 0)))
Proc _SetMode ("dot") ' we want dots, not pixels
 
For i = 0 to 50000
Proc _transformation (FUNC (_randomchoice))
 
Proc _SetColor (FUNC(_RGBtoColor (0, 128 + Rnd(128), 0)))
p = h - y/s
q = w/2 + x/s
 
Proc _SetPixel (p, q)
Next
 
Proc _SVGclose
End
 
_coefficients
Local (1)
 
Push 0 , 0 , 0 , 160 , 0 ' 1% of the time - f1
Push 200 , -260 , 230 , 220 , 1600 ' 7% of the time - f3
Push -150 , 280 , 260 , 240 , 440 ' 7% of the time - f4
Push 850 , 40 , -40 , 850 , 1600 ' 85% of the time - f2
 
For a@ = 19 To 0 Step -1 : @c(a@) = Pop() : Next
Return
 
_randomchoice
Local (1)
 
Push Rnd (100)
a@ = (Tos() > 0)
a@ = a@ + (Tos () > 7)
Return ((a@ + (Pop () > 14)) * 5)
 
_transformation
Param (1)
Local (2)
 
b@ = @c(a@) * x
b@ = (b@ + @c(a@+1) * y) / 1000
 
c@ = @c(a@+2) * x
c@ = (c@ + @c(a@+3) * y) / 1000
 
x = b@ : y = @c(a@+4) + c@
Return</syntaxhighlight>
 
=={{header|C}}==
Line 740 ⟶ 927:
 
bgcolor 0, 0, 0
cls graphics
 
for i = 1 to 10000
do
 
let r = rnd
Line 770 ⟶ 957:
let y = -.04 * x + .85 * y + 1.6
 
let x1 = ( x + 3 ) * 70
let y1 = 700 - y * 70
 
Line 776 ⟶ 963:
 
dot x1, y1
 
let n = n + 1
 
wait
 
next i</syntaxhighlight>
loop n < 10000
 
print "done"</syntaxhighlight>
 
=={{header|D}}==
Line 943 ⟶ 1,126:
 
=={{header|Emacs Lisp}}==
[[File:Barnsley fern emacs lisp.png|thumb|Output]]
<syntaxhighlight lang="lisp">; Barnsley fern
 
Line 1,327 ⟶ 1,511:
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/Barnsley_fern}}
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 &mdash;i.e. XML, JSON&mdash; they are intended for storage and transfer purposes more than visualization and edition.
 
'''Solution'''
Programs in Fōrmulæ are created/edited online in its [https://formulae.org website], However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.
 
[[File:Fōrmulæ - Barnsley fern 01.png]]
In '''[https://formulae.org/?example=Barnsley_fern this]''' page you can see the program(s) related to this task and their results.
 
'''Test case'''
 
[[File:Fōrmulæ - Barnsley fern 02.png]]
 
[[File:Fōrmulæ - Barnsley fern 03.png]]
 
=={{header|G'MIC}}==
Line 1,928 ⟶ 2,118:
=={{header|Locomotive Basic}}==
{{trans|ZX Spectrum Basic}}
[[File:Cpcbasic barnsley.png|thumb|Output with CPCBasic (graphics mode 3)]]
<syntaxhighlight lang="locobasic">10 mode 2:ink 0,0:ink 1,18:randomize time
20 scale=38
Line 2,019 ⟶ 2,210:
=={{header|Nim}}==
<syntaxhighlight lang="nim">
import nimPNG, std/random
 
randomize()
Line 2,067 ⟶ 2,258:
 
for i in 1..iterations:
var r = randomrand(101)
var nx, ny: float
if r <= 85:
Line 3,456 ⟶ 3,647:
call
demoWindow () ;
 
 
 
=={{header|SuperCollider }}==
{{works with|SuperCollider|3.13.0}}
Submitted to Rosetta Code 2024-06-07 by: MusicCoder.
 
The first line of code excuted is the LAST line in this listing: <br> drawFern.();
 
SuperCollider is a CLIENT / SERVER software system for the generation of music. <br>
CLIENT = (language+IDE) <br>
SERVER = (music-sound engine) <br>
However, the language is a complete / general purpose OO/functional programming language. <br>
SEE: <br>
https://supercollider.github.io/ <br>
https://en.wikipedia.org/wiki/SuperCollider <br>
 
<syntaxhighlight lang="SuperCollider">
// ==========================================================================
// START-SuperCollider solution to Rosetta Code TASK: Barnsley fern
// ==========================================================================
(
/* Barnsley_fern
https://rosettacode.org/wiki/Barnsley_fern
Create this fractal fern, using the following transformations:
ƒ1 1%: xn+1 = 0 yn+1 = 0.16 yn
ƒ2 85%: xn+1 = 0.85 xn + 0.04 yn yn+1 = −0.04 xn + 0.85 yn + 1.6
ƒ3 7% xn+1 = 0.2 xn − 0.26 yn yn+1 = 0.23 xn + 0.22 yn + 1.6
ƒ4 7% xn+1 = −0.15 xn + 0.28 yn yn+1 = 0.26 xn + 0.24 yn + 0.44.
Starting position: x = 0, y = 0
 
//BY: MusicCoder : 2024-06-07//
Create arrays to hold the various constants from the formulae above.
Replicate the arrays to create 100 of them,
*** biased by the percentages above ***.
Scramble the 100 arrays of constants.
Function nextXY will pick a set of constants at random and given the current
X and Y values will generate the next X and Y values.
Before we plot the X-Y values run function findScale so that we can make
sure the generated X & Y values will 'fit' within the bounds of the given display size.
 
SuperCollider is a CLIENT / SERVER software system for the generation of music.
CLIENT = (language+IDE)
SERVER = (music-sound engine)
However, the language is a complete / general purpose OO/functional programming language.
https://supercollider.github.io/
https://en.wikipedia.org/wiki/SuperCollider
*/
 
// ==========================================================================
// The first line of code executed is the LAST line in this listing:
// drawFern.();
// ==========================================================================
var fConstants =
// _NEXT_X___________ _NEXT_Y___________
// a*x + b*y +c d*x + e*y + f
( // duplicate each array of constants by the specified % number
([ 0.00, 0.00, 0.00, 0.00, 0.16, 0.00 ]!1 )++ // 1%
([ 0.85, 0.04, 0.00, -0.04, 0.85, 1.6 ]!85)++ // 85%
([ 0.2 , -0.26, 0.00, 0.23, 0.22, 1.6 ]!7 )++ // 7%
([-0.15, 0.28, 0.00, 0.26, 0.24, 0.44 ]!7) // 7%
// the ++ will construct a container array to hold theses arrays
).scramble; // randomly rearrange sub-arrays
// ==========================================================================
var fcSize = fConstants.size;
// ==========================================================================
var nextXY = {|x, y|
var a,b,c,d,e,f;
// split up the array of constants
#a,b,c,d,e,f = fConstants[fcSize.rand];
// apply the constants to the ADD and MUL operations on X and Y
// NEXT_X_________ NEXT_Y___________
[ (a*x) + (b*y) +c, (d*x) + (e*y) + f ]; // return new [x, y]
};
// ==========================================================================
var scaleAndShift = {|num, scale, shift|
roundUp((num*scale)+shift);
};
// ==========================================================================
var findScale = {|screenX=500, screenY=500, runs=1000, show=false|
// use to find min/max in loop of fern functions
var x=0, y=0;
// hold min/max results
var minX=x, maxX=x, minY=y, maxY=y;
// how much 'space' do the X and Y values need
var lengthX, lengthY;
var scaleX, scaleY;
 
// return the following 3 values to position & scale X and Y
// to stay within the given screen size
var shiftX=0; // add to generated X value to position X on screen
var shiftY=0; // add to generated Y value to position Y on screen
var scale; // multiply X and Y to scale the values to stay on the screen
// we need to use the same scaling factor for both X and Y to avoid distortion
 
// find min & max of both X and Y
runs.do {
#x, y = nextXY.(x, y);
if (x<minX) {minX=x};
if (x>maxX) {maxX=x};
if (y<minY) {minY=y};
if (y>maxY) {maxY=y};
};
 
// calculate amount of 'space' needed by X and by Y
lengthX = maxX-minX;
lengthY = maxY-minY;
scaleX = screenX/lengthX;
scaleY = screenY/lengthY;
 
// use the smaller of scaleX and scaleY as we need ONE scale to avoid distortion
// since we have only sampled possible X and Y values ...
// ... reduce scale to 90% of calculated value to allow space to larger X or Y
scale = 0.9*min(scaleX, scaleY);
 
// if min X or Y is negative 'shift' the ZERO point
// so that all neg and pos values are on the screen
if (minX.isNegative) {shiftX = minX.abs * scaleX};
if (minY.isNegative) {shiftY = minY.abs * scaleY};
 
// if calculated shift is 0, to move ZERO away from the edge
// set it as 1% of screen size
// (this is OK as we decreased scale by 10%)
if (shiftX ==0) {shiftX = screenX/100};
if (shiftY ==0) {shiftY = screenY/100};
 
// round up to nearest integer values
# scale, shiftX, shiftY = roundUp([scale, shiftX, shiftY ]);
 
if (show) {
var minXsas = scaleAndShift.(minX, scale, shiftX);
var maxXsas = scaleAndShift.(maxX, scale, shiftX);
var minYsas = scaleAndShift.(minY, scale, shiftY);
var maxYsas = scaleAndShift.(maxY, scale, shiftY);
postln("");
postf("scale=%, shiftX=%, shiftY=%\n", scale, shiftX, shiftY);
postf("MIN scaled & shifted X value=%\n", minXsas);
postf("MIN scaled & shifted Y value=%\n", minYsas);
postf("MAX scaled & shifted X value=% screenX=%\n", maxXsas, screenX);
postf("MAX scaled & shifted Y value=% screenY=%\n", maxYsas, screenY);
};
 
[scale, shiftX, shiftY]; // return these three values
};
// ==========================================================================
var drawFern = {|screenX=400, screenY=600, dotSize=1, windowCorner=50, runs=1000000|
 
var win = Window.new("Barnsley Fern", Rect(windowCorner, windowCorner, screenX, screenY)).front;
var x=0, y=0;
var bigX, bigY;
var scale, shiftX, shiftY;
 
# scale, shiftX, shiftY = findScale.(screenX, screenY, show: true);
win.view.background_(Color.white);
win.drawFunc = {
runs.do {|i|
# x, y = nextXY.(x, y); // generate next X and Y values
bigX = scaleAndShift.(x, scale, shiftX);
// Y=0 is at top of screen,
// so substract Y from screenY to flip orientation
bigY = screenY - scaleAndShift.(y, scale, shiftY);
Pen.color = Color.rand(); // *** JUST FOR FUN: pick a random color ***
Pen.addRect(Rect(bigX, bigY, dotSize, dotSize));
Pen.fill;
}; // end-of: do
}; // end-of: drawFunc
win.refresh;
}; // end-of: drawFern
// ==========================================================================
// The following line of code is executed first:
drawFern.();
)
// ==========================================================================
// **END-SuperCollider solution to Rosetta Code TASK: Barnsley fern
// ==========================================================================
</syntaxhighlight>
 
 
 
 
=={{header|Swift}}==
Line 3,693 ⟶ 4,063:
{{trans|Kotlin}}
{{libheader|DOME}}
<syntaxhighlight lang="ecmascriptwren">import "graphics" for Canvas, Color
import "dome" for Window
import "random" for Random
Line 3,746 ⟶ 4,116:
 
var Game = BarnsleyFern.new(640, 640, 200000)</syntaxhighlight>
 
{{out}}
[[File:Wren-Barnsley_fern.png|400px]]
 
=={{header|XPL0}}==
81

edits