Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita993215

Browse files
authored
add Koch snowflake (TheAlgorithms#2168)
* add KochSnowflake.java* add package
1 parent57bf40b commita993215

File tree

1 file changed

+234
-0
lines changed

1 file changed

+234
-0
lines changed

‎Others/KochSnowflake.java‎

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
packageOthers;
2+
3+
importjava.awt.*;
4+
importjava.awt.image.BufferedImage;
5+
importjava.io.File;
6+
importjava.io.IOException;
7+
importjava.util.ArrayList;
8+
importjavax.imageio.ImageIO;
9+
10+
/**
11+
* The Koch snowflake is a fractal curve and one of the earliest fractals to have been described.
12+
* The Koch snowflake can be built up iteratively, in a sequence of stages. The first stage is an
13+
* equilateral triangle, and each successive stage is formed by adding outward bends to each side of
14+
* the previous stage, making smaller equilateral triangles. This can be achieved through the
15+
* following steps for each line: 1. divide the line segment into three segments of equal length. 2.
16+
* draw an equilateral triangle that has the middle segment from step 1 as its base and points
17+
* outward. 3. remove the line segment that is the base of the triangle from step 2. (description
18+
* adapted from https://en.wikipedia.org/wiki/Koch_snowflake ) (for a more detailed explanation and
19+
* an implementation in the Processing language, see
20+
* https://natureofcode.com/book/chapter-8-fractals/ #84-the-koch-curve-and-the-arraylist-technique
21+
* ).
22+
*/
23+
publicclassKochSnowflake {
24+
25+
publicstaticvoidmain(String[]args) {
26+
// Test Iterate-method
27+
ArrayList<Vector2>vectors =newArrayList<Vector2>();
28+
vectors.add(newVector2(0,0));
29+
vectors.add(newVector2(1,0));
30+
ArrayList<Vector2>result =Iterate(vectors,1);
31+
32+
assertresult.get(0).x ==0;
33+
assertresult.get(0).y ==0;
34+
35+
assertresult.get(1).x ==1. /3;
36+
assertresult.get(1).y ==0;
37+
38+
assertresult.get(2).x ==1. /2;
39+
assertresult.get(2).y ==Math.sin(Math.PI /3) /3;
40+
41+
assertresult.get(3).x ==2. /3;
42+
assertresult.get(3).y ==0;
43+
44+
assertresult.get(4).x ==1;
45+
assertresult.get(4).y ==0;
46+
47+
// Test GetKochSnowflake-method
48+
intimageWidth =600;
49+
doubleoffsetX =imageWidth /10.;
50+
doubleoffsetY =imageWidth /3.7;
51+
BufferedImageimage =GetKochSnowflake(imageWidth,5);
52+
53+
// The background should be white
54+
assertimage.getRGB(0,0) ==newColor(255,255,255).getRGB();
55+
56+
// The snowflake is drawn in black and this is the position of the first vector
57+
assertimage.getRGB((int)offsetX, (int)offsetY) ==newColor(0,0,0).getRGB();
58+
59+
// Save image
60+
try {
61+
ImageIO.write(image,"png",newFile("KochSnowflake.png"));
62+
}catch (IOExceptione) {
63+
e.printStackTrace();
64+
}
65+
}
66+
67+
/**
68+
* Go through the number of iterations determined by the argument "steps". Be careful with high
69+
* values (above 5) since the time to calculate increases exponentially.
70+
*
71+
* @param initialVectors The vectors composing the shape to which the algorithm is applied.
72+
* @param steps The number of iterations.
73+
* @return The transformed vectors after the iteration-steps.
74+
*/
75+
publicstaticArrayList<Vector2>Iterate(ArrayList<Vector2>initialVectors,intsteps) {
76+
ArrayList<Vector2>vectors =initialVectors;
77+
for (inti =0;i <steps;i++) {
78+
vectors =IterationStep(vectors);
79+
}
80+
81+
returnvectors;
82+
}
83+
84+
/**
85+
* Method to render the Koch snowflake to a image.
86+
*
87+
* @param imageWidth The width of the rendered image.
88+
* @param steps The number of iterations.
89+
* @return The image of the rendered Koch snowflake.
90+
*/
91+
publicstaticBufferedImageGetKochSnowflake(intimageWidth,intsteps) {
92+
if (imageWidth <=0) {
93+
thrownewIllegalArgumentException("imageWidth should be greater than zero");
94+
}
95+
96+
doubleoffsetX =imageWidth /10.;
97+
doubleoffsetY =imageWidth /3.7;
98+
Vector2vector1 =newVector2(offsetX,offsetY);
99+
Vector2vector2 =
100+
newVector2(imageWidth /2,Math.sin(Math.PI /3) *imageWidth *0.8 +offsetY);
101+
Vector2vector3 =newVector2(imageWidth -offsetX,offsetY);
102+
ArrayList<Vector2>initialVectors =newArrayList<Vector2>();
103+
initialVectors.add(vector1);
104+
initialVectors.add(vector2);
105+
initialVectors.add(vector3);
106+
initialVectors.add(vector1);
107+
ArrayList<Vector2>vectors =Iterate(initialVectors,steps);
108+
returnGetImage(vectors,imageWidth,imageWidth);
109+
}
110+
111+
/**
112+
* Loops through each pair of adjacent vectors. Each line between two adjacent vectors is divided
113+
* into 4 segments by adding 3 additional vectors in-between the original two vectors. The vector
114+
* in the middle is constructed through a 60 degree rotation so it is bent outwards.
115+
*
116+
* @param vectors The vectors composing the shape to which the algorithm is applied.
117+
* @return The transformed vectors after the iteration-step.
118+
*/
119+
privatestaticArrayList<Vector2>IterationStep(ArrayList<Vector2>vectors) {
120+
ArrayList<Vector2>newVectors =newArrayList<Vector2>();
121+
for (inti =0;i <vectors.size() -1;i++) {
122+
Vector2startVector =vectors.get(i);
123+
Vector2endVector =vectors.get(i +1);
124+
newVectors.add(startVector);
125+
Vector2differenceVector =endVector.subtract(startVector).multiply(1. /3);
126+
newVectors.add(startVector.add(differenceVector));
127+
newVectors.add(startVector.add(differenceVector).add(differenceVector.rotate(60)));
128+
newVectors.add(startVector.add(differenceVector.multiply(2)));
129+
}
130+
131+
newVectors.add(vectors.get(vectors.size() -1));
132+
returnnewVectors;
133+
}
134+
135+
/**
136+
* Utility-method to render the Koch snowflake to an image.
137+
*
138+
* @param vectors The vectors defining the edges to be rendered.
139+
* @param imageWidth The width of the rendered image.
140+
* @param imageHeight The height of the rendered image.
141+
* @return The image of the rendered edges.
142+
*/
143+
privatestaticBufferedImageGetImage(
144+
ArrayList<Vector2>vectors,intimageWidth,intimageHeight) {
145+
BufferedImageimage =newBufferedImage(imageWidth,imageHeight,BufferedImage.TYPE_INT_RGB);
146+
Graphics2Dg2d =image.createGraphics();
147+
148+
// Set the background white
149+
g2d.setBackground(Color.WHITE);
150+
g2d.fillRect(0,0,imageWidth,imageHeight);
151+
152+
// Draw the edges
153+
g2d.setColor(Color.BLACK);
154+
BasicStrokebs =newBasicStroke(1);
155+
g2d.setStroke(bs);
156+
for (inti =0;i <vectors.size() -1;i++) {
157+
intx1 = (int)vectors.get(i).x;
158+
inty1 = (int)vectors.get(i).y;
159+
intx2 = (int)vectors.get(i +1).x;
160+
inty2 = (int)vectors.get(i +1).y;
161+
162+
g2d.drawLine(x1,y1,x2,y2);
163+
}
164+
165+
returnimage;
166+
}
167+
168+
/** Inner class to handle the vector calculations. */
169+
privatestaticclassVector2 {
170+
171+
doublex,y;
172+
173+
publicVector2(doublex,doubley) {
174+
this.x =x;
175+
this.y =y;
176+
}
177+
178+
@Override
179+
publicStringtoString() {
180+
returnString.format("[%f, %f]",this.x,this.y);
181+
}
182+
183+
/**
184+
* Vector addition
185+
*
186+
* @param vector The vector to be added.
187+
* @return The sum-vector.
188+
*/
189+
publicVector2add(Vector2vector) {
190+
doublex =this.x +vector.x;
191+
doubley =this.y +vector.y;
192+
returnnewVector2(x,y);
193+
}
194+
195+
/**
196+
* Vector subtraction
197+
*
198+
* @param vector The vector to be subtracted.
199+
* @return The difference-vector.
200+
*/
201+
publicVector2subtract(Vector2vector) {
202+
doublex =this.x -vector.x;
203+
doubley =this.y -vector.y;
204+
returnnewVector2(x,y);
205+
}
206+
207+
/**
208+
* Vector scalar multiplication
209+
*
210+
* @param scalar The factor by which to multiply the vector.
211+
* @return The scaled vector.
212+
*/
213+
publicVector2multiply(doublescalar) {
214+
doublex =this.x *scalar;
215+
doubley =this.y *scalar;
216+
returnnewVector2(x,y);
217+
}
218+
219+
/**
220+
* Vector rotation (see https://en.wikipedia.org/wiki/Rotation_matrix)
221+
*
222+
* @param angleInDegrees The angle by which to rotate the vector.
223+
* @return The rotated vector.
224+
*/
225+
publicVector2rotate(doubleangleInDegrees) {
226+
doubleradians =angleInDegrees *Math.PI /180;
227+
doubleca =Math.cos(radians);
228+
doublesa =Math.sin(radians);
229+
doublex =ca *this.x -sa *this.y;
230+
doubley =sa *this.x +ca *this.y;
231+
returnnewVector2(x,y);
232+
}
233+
}
234+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp