Koch curve: Difference between revisions

15,074 bytes added ,  1 month ago
m
m (syntax highlighting fixup automation)
 
(36 intermediate revisions by 11 users not shown)
Line 193:
end Koch_Curve;</syntaxhighlight>
 
=={{header|BASIC256ALGOL 68}}==
{{libheader|ALGOL 68-l-system}}
<syntaxhighlight lang="basic256">global RtoD, DtoR
Generates an SVG file containing the curve using the L-System. Very similar to the Algol 68 [[Sierpinski square curve]] sample.
RtoD = 180 / Pi
<br/>
DtoR = Pi / 180
Note the Algol 68 L-System library source code is on a separate page on Rosetta Code - follow the above link and then to the Talk page.
<syntaxhighlight lang="algol68">
BEGIN # Koch Curve in SVG #
# uses the RC Algol 68 L-System library for the L-System evaluation & #
# interpretation #
 
PR read "lsystem.incl.a68" PR # include L-System utilities #
global posX, posY, angulo
posX = 170 : posY = 100 : angulo = 0
 
PROC koch curve = ( STRING fname, INT size, length, order, init x, init y )VOID:
global ancho, alto
IF FILE svg file;
ancho = 650 : alto = 650
BOOL open error := IF open( svg file, fname, stand out channel ) = 0
graphsize ancho, alto
THEN
# opened OK - file already exists and #
# will be overwritten #
FALSE
ELSE
# failed to open the file #
# - try creating a new file #
establish( svg file, fname, stand out channel ) /= 0
FI;
open error
THEN # failed to open the file #
print( ( "Unable to open ", fname, newline ) );
stop
ELSE # file opened OK #
 
REAL x := init x;
subroutine kochLado(longitud, fondo)
REAL y := init y;
if fondo = 0 then
INT angle := 0;
dx = cos(angulo*DtoR) * longitud
put( svg file, ( "<svg xmlns='http://www.w3.org/2000/svg' width='"
dy = sin(angulo*DtoR) * longitud
, whole( size, 0 ), "' height='", whole( size, 0 ), "'>"
color rgb(5,100,24)
, newline, "<rect width='100%' height='100%' fill='white'/>"
line (posX, posY, posX+dx, posY+dy)
, newline, "<path stroke-width='1' stroke='black' fill='none' d='"
posX += dx
, newline, "M", whole( x, 0 ), ",", whole( y, 0 ), newline
posY += dy
)
else
);
call kochLado(longitud/3.0, fondo-1)
angulo += 60
call kochLado(longitud/3.0, fondo-1)
angulo -= 120
call kochLado(longitud/3.0, fondo-1)
angulo += 60
call kochLado(longitud/3.0, fondo-1)
end if
end subroutine
 
LSYSTEM ssc = ( "F++F++F"
subroutine CopoNieveKoch(longitud, recursionfondo)
, ( "F" -> "F-F++F-F"
for i = 1 to 6
)
call kochLado(longitud,recursionfondo)
);
angulo -= 300
STRING curve = ssc EVAL order;
next i
curve INTERPRET ( ( CHAR c )VOID:
end subroutine
IF c = "F" THEN
x +:= length * cos( angle * pi / 180 );
y +:= length * sin( angle * pi / 180 );
put( svg file, ( " L", whole( x, 0 ), ",", whole( y, 0 ), newline ) )
ELIF c = "+" THEN
angle +:= 60 MODAB 360
ELIF c = "-" THEN
angle -:= 60 MODAB 360
FI
);
put( svg file, ( "'/>", newline, "</svg>", newline ) );
close( svg file )
FI # sierpinski square # ;
 
koch curve( "koch.svg", 600, 5, 4, 150, 150 )
for n = 0 To 7
clg
fastgraphics
text 3,4, "Copo de nieve de Koch"
text 4,16, "Iteración número: " & n
call CopoNieveKoch(280, n)
pause 0.8
refresh
next n
 
END
imgsave "Koch_curve.jpg", "jpg"
end</syntaxhighlight>
 
=={{header|Amazing Hopper}}==
Line 339 ⟶ 355:
back
</syntaxhighlight>
 
 
=={{header|AutoHotkey}}==
Line 425 ⟶ 440:
ExitApp
Return</syntaxhighlight>
 
=={{header|BASIC256}}==
<syntaxhighlight lang="basic256">global RtoD, DtoR
RtoD = 180 / Pi
DtoR = Pi / 180
 
global posX, posY, angulo
posX = 170 : posY = 100 : angulo = 0
 
global ancho, alto
ancho = 650 : alto = 650
graphsize ancho, alto
 
subroutine kochLado(longitud, fondo)
if fondo = 0 then
dx = cos(angulo*DtoR) * longitud
dy = sin(angulo*DtoR) * longitud
color rgb(5,100,24)
line (posX, posY, posX+dx, posY+dy)
posX += dx
posY += dy
else
call kochLado(longitud/3.0, fondo-1)
angulo += 60
call kochLado(longitud/3.0, fondo-1)
angulo -= 120
call kochLado(longitud/3.0, fondo-1)
angulo += 60
call kochLado(longitud/3.0, fondo-1)
end if
end subroutine
 
subroutine CopoNieveKoch(longitud, recursionfondo)
for i = 1 to 6
call kochLado(longitud,recursionfondo)
angulo -= 300
next i
end subroutine
 
for n = 0 To 7
clg
fastgraphics
text 3,4, "Copo de nieve de Koch"
text 4,16, "Iteración número: " & n
call CopoNieveKoch(280, n)
pause 0.8
refresh
next n
 
imgsave "Koch_curve.jpg", "jpg"
end</syntaxhighlight>
 
=={{header|C}}==
Line 563 ⟶ 629:
 
{{out}}
[[Media:Koch_curve_cpp.svg]]
See: [https://slack-files.com/T0CNUL56D-F016A5L6J5D-3c32740a46 koch_curve.svg] (offsite SVG image)
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|Windows,Forms,SysUtils,Types,ExtCtrls,Graphics}}
Fancy version, shows six iterations of both single-line and triangle version drawn to graphics screen. Uses vector libraries to simplify the process
 
[[File:DelphiKochSNowflake2.png|thumb|none]]
 
<syntaxhighlight lang="Delphi">
{===== These routines would normally be in extermal ======}
{===== libraries, but they are presented here for clarity ======}
 
type T2DVector=packed record
X,Y: double;
end;
 
type T2DLine = packed record
P1,P2: T2DVector;
end;
 
procedure ClearImage(Image: TImage; Color: TColor);
var R: TRect;
begin
R:=Rect(0,0,Image.Picture.Bitmap.Width,Image.Picture.Bitmap.Height);
Image.Canvas.Brush.Color:=Color;
Image.Canvas.Brush.Style:=bsSolid;
Image.Canvas.Pen.Mode:=pmCopy;
Image.Canvas.Pen.Style:=psSolid;
Image.Canvas.Pen.Color:=Color;
Image.Canvas.Rectangle(R);
Image.Invalidate;
end;
 
 
 
procedure DrawLine2D(Canvas: TCanvas; L: T2DLine; C: TColor);
{Draw Line on specified canvas}
begin
Canvas.Pen.Color:=C;
Canvas.MoveTo(Trunc(L.P1.X),Trunc(L.P1.Y));
Canvas.LineTo(Trunc(L.P2.X),Trunc(L.P2.Y));
end;
 
 
 
function MakeVector2D(const X,Y: double): T2DVector;
{Create 2D Vector from X and Y}
begin
Result.X:=X;
Result.Y:=Y;
end;
 
 
function VectorAdd2D(const V1,V2: T2DVector): T2DVector;
{Add V1 and V2}
begin
Result.X:= V1.X + V2.X;
Result.Y:= V1.Y + V2.Y;
end;
 
 
function VectorSubtract2D(const V1,V2: T2DVector): T2DVector;
{Subtract V2 from V1}
begin
Result.X:= V1.X - V2.X;
Result.Y:= V1.Y - V2.Y;
end;
 
 
function VectorABS2D(const V: T2DVector): double;
{Find ABS of vector}
begin
Result:=Sqrt(Sqr(V.X) + Sqr(V.Y));
end;
 
 
function LineLength2D(const L: T2DLine) : double; overload;
{ Find length of a line defined by P1 and P2 }
begin
Result:=VectorABS2D(VectorSubtract2D(L.P2,L.P1));
end;
 
 
 
function ScalarDivide2D(const V: T2DVector; const S: double): T2DVector;
{Divide vector by scalar}
begin
Result.X:=V.X / S;
Result.Y:=V.Y / S;
end;
 
 
 
function ScalarProduct2D(const V: T2DVector; const S: double): T2DVector;
{Multiply vector by scalar}
begin
Result.X:=V.X * S;
Result.Y:=V.Y * S;
end;
 
 
function UnitVector2D(const V: T2DVector): T2DVector;
{Return unit vector}
var L: double;
begin
L:=VectorABS2D(V);
if L=0.0 then L:=1E-99;
Result.X:=V.X / L;
Result.Y:=V.Y / L;
end;
 
 
function GetUnitNormal2D(const V: T2DVector): T2DVector; overload;
{Returns perpendicular unit vector}
begin
Result:=UnitVector2D(MakeVector2D(-V.Y, V.X));
end;
 
 
function ExtendLine2D(const L1: T2DLine; const Len: double): T2DVector;
{ Return a point that extends line L1 by Len }
var Len1,UX,UY : double;
begin
Len1 := LineLength2D(L1)+1E-9;
UX := (L1.P2.X - L1.P1.X)/Len1;
UY := (L1.P2.Y - L1.P1.Y)/Len1;
Result.X := L1.P2.X +(UX *Len);
Result.Y := L1.P2.Y+(UY *Len);
end;
 
 
 
{---------------------------------------------------------------------------}
 
{Array of lines to contain the snow flake}
 
type TLineArray = array of T2DLine;
 
{Screen and display parameters}
 
var ScreenSize: TPoint;
var SquareBox: TRect;
var BoxSize: integer;
 
procedure ConfigureScreen(Image: TImage);
{Setup screen parameters based Image component}
begin
ScreenSize:=Point(Image.Width, Image.Height);
if ScreenSize.X<ScreenSize.Y then BoxSize:=ScreenSize.X
else BoxSize:=ScreenSize.Y;
SquareBox:=Rect(0,0,BoxSize,BoxSize);
OffsetRect(SquareBox,(ScreenSize.X-BoxSize) div 2,(ScreenSize.Y-BoxSize) div 2);
end;
 
 
procedure DrawLines(Canvas: TCanvas; Lines: TLineArray);
{Draw all the lines in the snow flake}
var I: integer;
begin
for I:=0 to High(Lines) do
DrawLine2D(Canvas,Lines[I],clRed);
end;
 
 
procedure BreakLine(L: T2DLine; var L1,L2,L3,L4: T2DLine);
{Break one line into the four new lines of the next iteration}
var Len,Len3,O: double;
var Delta: TPoint;
var P1,P2,P3,P4,P5,Half: T2DVector;
begin
Len:=LineLength2D(L);
Len3:=Len/3;
O:= Sqrt(sqr(Len3)-sqr(Len3/2));
P1:=L.P1;
P2:=ExtendLine2D(L,-Len3*2);
P4:=ExtendLine2D(L,-Len3);
P5:=L.P2;
Half:=ScalarDivide2D(VectorAdd2D(P4,P2),2);
P3:=GetUnitNormal2D(VectorSubtract2D(P4,P2));
P3:=ScalarProduct2D(P3,O);
P3:=VectorAdd2D(P3,Half);
L1.P1:=P1; L1.P2:=P2;
L2.P1:=P2; L2.P2:=P3;
L3.P1:=P3; L3.P2:=P4;
L4.P1:=P4; L4.P2:=P5;
end;
 
 
 
procedure BreakAndStoreLines(Line: T2DLine; var Lines: TLineArray);
{Break one line and store the resulting four in array}
var Len: integer;
begin
Len:=Length(Lines);
SetLength(Lines,Len+4);
BreakLine(Line, Lines[Len+0],Lines[Len+1],Lines[Len+2],Lines[Len+3]);
end;
 
 
procedure BreakArray(var Lines: TLineArray);
{Break all the lines in an array and replace them with new lines}
var I: integer;
var AT: TLineArray;
begin
AT:=Lines;
SetLength(Lines,0);
for I:=0 to High(AT) do
BreakAndStoreLines(AT[I], Lines);
end;
 
procedure LineSeed(var Lines: TLineArray);
{Put single line seed in array}
var Border: integer;
begin
Border:=MulDiv(BoxSize,10,100);
SetLength(Lines,1);
Lines[0].P1:=MakeVector2D(SquareBox.Left + Border, SquareBox.Top + Border);
Lines[0].P2:=MakeVector2D(SquareBox.Right - Border, SquareBox.Top + Border);
end;
 
 
procedure TriangleSeed(var Lines: TLineArray);
{Put triangle seed in array}
const Border = 15;
var R: TRect;
var PixelBorder: integer;
var H: double;
begin
SetLength(Lines,3);
PixelBorder:=MulDiv(BoxSize,Border,100);
R.Left:=SquareBox.Left + PixelBorder;
R.Right:=SquareBox.Right - PixelBorder;
R.Top:=SquareBox.Top + MulDiv(PixelBorder,1414,1000);
R.Bottom:=SquareBox.Bottom - PixelBorder;
OffsetRect(R,0,-MulDiv(BoxSize,15,100));
 
Lines[0].P1:=MakeVector2D(R.Left, R.Bottom);
Lines[0].P2:=MakeVector2D(R.Right, R.Bottom);
 
Lines[1].P1:=Lines[0].P2;
Lines[1].P2:=MakeVector2D((R.Right+R.Left) div 2,R.Top);
 
Lines[2].P1:=Lines[1].P2;
Lines[2].P2:=Lines[0].P1;
end;
 
 
 
procedure DoKochSnowFlake(Image: TImage);
{Construct and display various Koch snow flakes}
var Lines: TLineArray;
 
procedure IterateSnowflakes;
{Iterate through six phases of snow flakes}
var I,J: integer;
begin
for I:=1 to 6 do
begin
ClearImage(Image,clWhite);
Image.Canvas.Pen.Color:=clBlack;
Image.Canvas.Rectangle(SquareBox);
Image.Canvas.TextOut(10, 15, IntToStr(I)+' '+IntToStr(Length(Lines)));
DrawLines(Image.Canvas,Lines);
Image.Repaint;
Sleep(2000);
BreakArray(Lines);
end;
end;
 
 
begin
ConfigureScreen(Image);
{Iterate snow flake line}
LineSeed(Lines);
IterateSnowflakes;
{Iterate snow flake triangle}
TriangleSeed(Lines);
IterateSnowflakes;
end;
 
</syntaxhighlight>
{{out}}
[[File:DelphiKochSNowflake1.png|thumb|none]]
<pre>
</pre>
 
=={{header|EasyLang}}==
 
[https://easylang.dev/show/#cod=ZZLdUoMwEIXv8xTn0tohhp/WK3wXB6llrKQDjCZv754lFWOvIOfbs3uycJ18hw/fnRFKxBKhQqwwLP0EC2sAhBotHoQ+osJeCnZ4Qk0SlcQbiRsJTfKwnnjzNMnD+oyEgxAZthdjg0Jed8I7P+PoKEaKUcV5GEXUdjRJjiIzrfyfae1E03BaL/gCPVLhsWhRpvPfhdTsz4KMqSqRJcAdU1XiyPA7puq2ZLL+Mvep5jKM/To3EzgsEzghE9g2EziBgjXWUPke3pYznK2NtJeLHkzks3bm03/dZp78hNfxXXSHeemvKCuHxaNqdFHStIV+1GeXFirV+hlI4i/h/hO5+7U0pmYIGlBjSFZrfgA= Run it]
 
<syntaxhighlight lang="easylang">
proc koch x1 y1 x2 y2 iter . .
x3 = (x1 * 2 + x2) / 3
y3 = (y1 * 2 + y2) / 3
x4 = (x1 + x2 * 2) / 3
y4 = (y1 + y2 * 2) / 3
x5 = x3 + (x4 - x3) * cos 60 + (y4 - y3) * sin 60
y5 = y3 - (x4 - x3) * sin 60 + (y4 - y3) * cos 60
if iter > 0
iter -= 1
koch x1 y1 x3 y3 iter
koch x3 y3 x5 y5 iter
koch x5 y5 x4 y4 iter
koch x4 y4 x2 y2 iter
else
line x1 y1
line x3 y3
line x5 y5
line x4 y4
line x2 y2
.
.
linewidth 0.3
x1 = 15
y1 = 30
move x1 y1
for ang = 0 step 120 to 240
x2 = x1 + 70 * cos ang
y2 = y1 + 70 * sin ang
koch x1 y1 x2 y2 4
x1 = x2
y1 = y2
.
</syntaxhighlight>
 
=={{header|Factor}}==
Line 697 ⟶ 1,087:
End
</syntaxhighlight>
 
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/L-system}}
 
'''Solution'''
 
It can be done using an [[wp:L-system|L-system]]. There are generic functions written in Fōrmulæ to compute an L-system in the page [[L-system#Fōrmulæ | L-system]].
 
The program that creates a Koch curve is:
 
[[File:Fōrmulæ - L-system - Koch's snowflake 01.png]]
 
[[File:Fōrmulæ - L-system - Koch's snowflake 02.png]]
 
=={{header|Go}}==
Line 888 ⟶ 1,292:
plot koch ^: 5 tri</syntaxhighlight>
 
[[j:File:J-Koch-snowflake.png|example]]
 
The idea is to continually expand the segments between a list of points in the complex plane. Given consecutive x and y in the list, v = (y-x)/3 is a vector representing 1/3 of the trip from x to y. An iteration building the Koch curve starts at x, advances by v, advances by v rotated by 60 degrees, advances by v rotated -60 degrees, and finally advances by another v, reaching y. x seg y produces this expansion. koch takes a list of points and expands segments between consecutive ones, producing another list. koch ^: 5 does this 5 times, and plot shows the snowflake in a window.
 
=={{header|Java}}==
<syntaxhighlight lang="java">
 
import java.awt.Point;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
 
public final class KochCurve {
public static void main(String[] aArgs) throws IOException {
List<Point> points = initialEquilateralTriangle();
for ( int i = 1; i < 5; i++ ) {
points = nextIteration(points);
}
String text = kochCurveText(points, IMAGE_SIZE);
Files.write(Paths.get("C:/Users/psnow/Desktop/koch.svg"), text.getBytes());
}
private static List<Point> initialEquilateralTriangle() {
final int margin = 50;
final int boxSize = IMAGE_SIZE - margin;
final int sideLength = Math.round(boxSize * SIN_60_DEGREES);
final int x = ( boxSize + margin - sideLength ) / 2;
final int y = Math.round(( boxSize + margin ) / 2 - sideLength * SIN_60_DEGREES / 3);
List<Point> points = Arrays.asList(
new Point(x, y),
new Point(x + sideLength / 2, Math.round(y + sideLength * SIN_60_DEGREES)),
new Point(x + sideLength, y),
new Point(x, y)
);
return points;
}
private static List<Point> nextIteration(List<Point> aPoints) {
List<Point> result = new ArrayList<Point>();
for ( int i = 0; i < aPoints.size() - 1; i++ ) {
final int x0 = aPoints.get(i).x;
final int y0 = aPoints.get(i).y;
final int x1 = aPoints.get(i + 1).x;
final int y1 = aPoints.get(i + 1).y;
final int dy = y1 - y0;
final int dx = x1 - x0;
result.add(aPoints.get(i));
result.add( new Point(x0 + dx / 3, y0 + dy / 3) );
result.add( new Point(Math.round(x0 + dx / 2 - dy * SIN_60_DEGREES / 3),
Math.round(y0 + dy / 2 + dx * SIN_60_DEGREES / 3)) );
result.add( new Point(x0 + 2 * dx / 3, y0 + 2 * dy / 3) ) ;
}
result.add(aPoints.get(aPoints.size() - 1));
return result;
}
private static String kochCurveText(List<Point> aPoints, int aSize) {
StringBuilder text = new StringBuilder();
text.append("<svg xmlns='http://www.w3.org/2000/svg'");
text.append(" width='" + aSize + "' height='" + aSize + "'>\n");
text.append("<rect style='width:100%;height:100%;fill:cyan'/>\n");
text.append("<polygon points='");
for ( int i = 0; i < aPoints.size(); i++ ) {
text.append(aPoints.get(i).x + ", " + aPoints.get(i).y + " ");
}
text.append("' style='fill:pink;stroke:black;stroke-width:2'/>\n</svg>\n");
return text.toString();
}
private static final int IMAGE_SIZE = 700;
private static final float SIN_60_DEGREES = (float) Math.sin(Math.PI / 3.0);
}
</syntaxhighlight>
{{ out }}
[[Media:kochCurve.svg]]
 
=={{header|JavaScript}}==
Line 1,368 ⟶ 1,856:
{{works with|FMSLogo}}
 
<syntaxhighlight lang="fmslogo">
<lang >
to ff :l :i
cs
Line 1,599 ⟶ 2,087:
GeometricTransformation[KochCurve[5], RotationTransform[-Pi/3, {1, 0}]],
GeometricTransformation[KochCurve[5], RotationTransform[Pi/3, {0, 0}]]}]</syntaxhighlight>
 
=={{header|Maxima}}==
Using [https://riotorto.users.sourceforge.net/Maxima/gnuplot/turtle/turtle.mac turtle.mac] package for turtle graphics in Maxima.
<syntaxhighlight lang="maxima">
set_draw_defaults(
terminal = svg,
dimensions = [350,350],
proportional_axes = xy) $
 
wxdraw2d(
turtle(
to(koch_snowflake, [n, len],
ifelse(n = 0,
[forward(len)],
[koch_snowflake(n - 1, len),
right(60),
koch_snowflake(n - 1, len),
left(120),
koch_snowflake(n - 1, len),
right(60),
koch_snowflake(n - 1, len)]
)
),
repeat(6,
koch_snowflake(5, 300),
right(60)
)
)
);
</syntaxhighlight>
[[File:KochSnowflake.png|thumb|center]]
 
=={{header|Nim}}==
Line 1,913 ⟶ 2,432:
 
{{out}}
[[Media:Koch_snowflake_prolog.svg]]
See: [https://slack-files.com/T0CNUL56D-F0173G7T8CR-80ae9200ba koch_snowflake.svg] (offsite SVG image)
 
=={{header|Python}}==
Line 2,333 ⟶ 2,852:
turtle
20 frames
witheach
[ dup char F = iff
Line 2,338 ⟶ 2,858:
char L = iff
[ -1 6 turn ] done
1 6 turn ]</syntaxhighlight>
1 frames</syntaxhighlight>
 
{{output}}
 
[[File:Quackery Koch curve.png]]
https://imgur.com/pOeCUVH
 
=={{header|Racket}}==
Line 2,689 ⟶ 3,210:
 
{{out}}
[[Media:Koch_snowflake_rust.svg]]
See: [https://slack-files.com/T0CNUL56D-F016A5RCWPR-5e7c5a723a koch_snowflake.svg] (offsite SVG image)
 
=={{header|Sidef}}==
Line 2,829 ⟶ 3,350:
{{trans|Go}}
{{libheader|DOME}}
<syntaxhighlight lang="ecmascriptwren">import "graphics" for Canvas, Color, Point
import "dome" for Window
import "math" for M
3,028

edits