Barnsley fern: Difference between revisions

Content deleted Content added
Asub (talk | contribs)
Chkas (talk | contribs)
 
(9 intermediate revisions by 7 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 912 ⟶ 1,099:
=={{header|EasyLang}}==
 
[https://easylang.devonline/apps/barnsley-fern.html Run it]
 
<syntaxhighlight lang="text">
color 060
for i = 1 to 200000
Line 939 ⟶ 1,126:
 
=={{header|Emacs Lisp}}==
[[File:Barnsley fern emacs lisp.png|thumb|Output]]
<syntaxhighlight lang="lisp">; Barnsley fern
 
Line 1,930 ⟶ 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,150 ⟶ 2,339:
END BarnsleyFern.
</syntaxhighlight>
 
=={{header|Oberon-07}}==
 
The Barnsley fern is one of the examples distributed with [[Oberonc (Oberon-07 compiler for the JVM)]], source and bitmap on [https://github.com/lboasso/oberonc/tree/master/examples/fern github].
 
=={{header|PARI/GP}}==
Line 3,458 ⟶ 3,651:
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,546 ⟶ 3,918:
I+1→I
End</syntaxhighlight>
 
=={{header|Uiua}}==
Sideways fern for a change :-)
[https://uiua.org/pad?src=0_12_0-dev_1__RnMg4oaQIFtbWzAgMCAwXSBbMCAwLjE2IDBdXQogICAgICBbWzAuODUgMC4wNCAwXSBbwq8wLjA0IDAuODUgMS42XV0KICAgICAgW1swLjIgwq8wLjI2IDBdIFswLjIzIDAuMjIgMS42XV0KICAgICAgW1vCrzAuMTUgMC4yOCAwXSBbMC4yNiAwLjI0IDAuNDRdXV0KUHMg4oaQIFsxIDg2IDkzIDEwMF0KUGlja0Yg4oaQICjiiqE6RnPiiqLiipo8UHPijIrDl-KagjEwMCkKTmV4dCDihpAg4omhLyvDl1BpY2tGwqTiioI6MQpb4o2lKE5leHQuKTk5OTk5IDBfMF0KUyDihpAgNjAwCivCpFvDtzRTIDBd4oyKLTHDl1PDty_ihqUv4oalLi3CpC_ihqcuICAjIFNjYWxlLgriiKco4o2c4oqh4ouFMF8xXzApOuKGr1NfU18zIFswIDAgMF0gIyBQbG90Lgo= Run it in Uiua Pad!]
<syntaxhighlight lang="uiua">
Fs ← [[[0 0 0] [0 0.16 0]]
[[0.85 0.04 0] [¯0.04 0.85 1.6]]
[[0.2 ¯0.26 0] [0.23 0.22 1.6]]
[[¯0.15 0.28 0] [0.26 0.24 0.44]]]
Ps ← [1 86 93 100]
PickF ← (⊡:Fs⊢⊚<Ps⌊×⚂100)
Next ← ≡/+×PickF¤⊂:1
[⍥(Next.)99999 0_0]
S ← 600
+¤[÷4S 0]⌊-1×S÷/↥/↥.-¤/↧. # Scale.
∧(⍜⊡⋅0_1_0):↯S_S_3 [0 0 0] # Plot.
</syntaxhighlight>
{{out}}
[[File:Uiua Barnsley Fern.png|thumb|center]]
 
=={{header|Unicon}}==
Line 3,695 ⟶ 4,086:
{{trans|Kotlin}}
{{libheader|DOME}}
<syntaxhighlight lang="ecmascriptwren">import "graphics" for Canvas, Color
import "dome" for Window
import "random" for Random
Line 3,748 ⟶ 4,139:
 
var Game = BarnsleyFern.new(640, 640, 200000)</syntaxhighlight>
 
{{out}}
[[File:Wren-Barnsley_fern.png|400px]]
 
=={{header|XPL0}}==