-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkoch.html
More file actions
392 lines (350 loc) · 22.8 KB
/
Copy pathkoch.html
File metadata and controls
392 lines (350 loc) · 22.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Koch - C++ Mode Examples</title>
<style>* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: #111; background: #fff; }
a { color: #111; text-decoration: none; }
nav { border-bottom: 1px solid #e0e0e0; padding: 0 2rem; display: flex; align-items: center; justify-content: space-between; height: 60px; position: sticky; top: 0; background: #fff; z-index: 100; }
.hamburger { background: none; border: none; cursor: pointer; font-size: 22px; padding: 4px 8px; display: none; }
.layout { display: flex; min-height: calc(100vh - 60px); }
.sidebar-outer { width: 220px; min-width: 220px; border-right: 1px solid #e0e0e0; display: flex; flex-direction: column; position: sticky; top: 60px; height: calc(100vh - 60px); }
#site-sidebar { padding: 1.5rem 1.5rem 1rem; border-bottom: 1px solid #e0e0e0; display: flex; flex-direction: column; }
#site-sidebar a { font-size: 14px; color: #555; padding: 0.4rem 0; display: block; }
#site-sidebar a:hover { color: #111; }
#site-sidebar a.active { color: #111; font-weight: 500; }
.sidebar-examples { flex: 1; overflow-y: auto; }
.section-header { display: flex; justify-content: space-between; align-items: center; padding: 0.85rem 1.5rem; font-size: 13px; font-weight: 600; color: #111; cursor: pointer; border-bottom: 1px solid #e0e0e0; user-select: none; }
.section-header:hover { background: #f8f8f8; }
.arrow { font-size: 11px; color: #aaa; }
.category { margin-bottom: 0.25rem; }
.category-title { font-size: 11px; font-weight: 600; color: #aaa; text-transform: uppercase; letter-spacing: 0.08em; padding: 0.75rem 1.5rem 0.25rem; }
.category a { display: block; font-size: 13px; color: #555; padding: 0.3rem 1.5rem; }
.category a:hover { color: #111; background: #f8f8f8; }
.category a.active { color: #111; font-weight: 500; background: #f4f4f4; }
.content { flex: 1; padding: 3rem 4rem; max-width: 900px; }
.content h1 { font-size: 1.8rem; font-weight: 600; margin-bottom: 0.75rem; color: #e8b400; }
.preview-wrap { border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden; margin-bottom: 2rem; display: block; max-width: 100%; width: fit-content; }
.preview-wrap iframe { display: block; border: none; max-width: 100%; }
.code-block { background: #f8f8f8; border-radius: 8px; overflow: hidden; }
.code-header { padding: 0.75rem 1.25rem; border-bottom: 1px solid #e0e0e0; font-size: 12px; color: #888; font-family: monospace; display: flex; align-items: center; justify-content: space-between; }
.copy-btn { font-size: 12px; color: #555; background: #fff; border: 1px solid #ddd; border-radius: 4px; padding: 3px 10px; cursor: pointer; font-family: inherit; }
.copy-btn:hover { background: #f0f0f0; }
.copy-btn.copied { color: #090; border-color: #090; }
pre { padding: 1.5rem; font-family: "SF Mono","Fira Code",monospace; font-size: 13px; line-height: 1.7; overflow-x: auto; white-space: pre; }
.welcome h1 { font-size: 1.8rem; font-weight: 600; margin-bottom: 1rem; }
.welcome p { color: #555; line-height: 1.8; max-width: 500px; }
footer { border-top: 1px solid #e0e0e0; padding: 2rem; text-align: center; font-size: 13px; color: #888; }
.footer-contact { margin-top: 0.4rem; font-size: 12px; }
.footer-contact a { color: #aaa; border-bottom: 1px solid transparent; }
.footer-contact a:hover { color: #111; border-bottom-color: #111; }
.footer-sep { color: #ccc; margin: 0 0.5rem; }
@media (max-width: 768px) {
.hamburger { display: block; }
.sidebar-outer { position: fixed; top: 60px; left: -240px; width: 240px; height: calc(100vh - 60px); background: #fff; z-index: 200; transition: left 0.25s ease; box-shadow: 2px 0 12px rgba(0,0,0,0.08); }
.sidebar-outer.open { left: 0; }
.content { padding: 2rem 1.25rem; }
.preview-wrap { max-width: 100%; }
pre { font-size: 12px; }
}</style>
</head>
<body>
<nav id="site-nav">
<button class="hamburger" onclick="document.querySelector('.sidebar-outer').classList.toggle('open')">☰</button>
</nav>
<div class="layout">
<div class="sidebar-outer">
<div id="site-sidebar">
<a href="../libraries">Libraries</a>
<a href="../reference">Reference</a>
<a href="../examples">Examples</a>
<a href="../about">About</a>
</div>
<div class="sidebar-examples"><div class="section-header" onclick="toggleSection('basics')"><span>Basics</span><span class="arrow" id="basics-arrow">▾</span></div><div id="basics-section" style="display:block"><div class="category"><div class="category-title">Arrays</div><a href="array.html" >Array</a><a href="array-2d.html" >Array 2D</a><a href="array-objects.html" >Array Objects</a></div><div class="category"><div class="category-title">Camera</div><a href="move-eye.html" >Move Eye</a><a href="perspective.html" >Perspective</a><a href="perspective-vs-ortho.html" >Perspective vs Ortho</a></div><div class="category"><div class="category-title">Color</div><a href="brightness.html" >Brightness</a><a href="color-variables.html" >Color Variables</a><a href="hue.html" >Hue</a><a href="radial-gradient.html" >Radial Gradient</a><a href="relativity.html" >Relativity</a><a href="saturation.html" >Saturation</a><a href="simple-linear-gradient.html" >Simple Linear Gradient</a></div><div class="category"><div class="category-title">Control</div><a href="conditionals-1.html" >Conditionals 1</a><a href="conditionals-2.html" >Conditionals 2</a><a href="embedding-iteration.html" >Embedding Iteration</a><a href="iteration.html" >Iteration</a><a href="logical-operators.html" >Logical Operators</a></div><div class="category"><div class="category-title">Data</div><a href="characters-strings.html" >Characters Strings</a><a href="datatype-conversion.html" >Datatype Conversion</a><a href="integers-floats.html" >Integers Floats</a><a href="true-false.html" >True False</a><a href="variable-scope.html" >Variable Scope</a><a href="variables.html" >Variables</a></div><div class="category"><div class="category-title">Forms</div><a href="bezier.html" >Bezier</a><a href="pie-chart.html" >Pie Chart</a><a href="points-and-lines.html" >Points and Lines</a><a href="primitives-3d.html" >Primitives 3D</a><a href="regular-polygon.html" >Regular Polygon</a><a href="shape-primitives.html" >Shape Primitives</a><a href="star.html" >Star</a><a href="triangle-strip.html" >Triangle Strip</a></div><div class="category"><div class="category-title">Image</div><a href="alpha-mask.html" >Alpha Mask</a><a href="background-image.html" >Background Image</a><a href="create-image.html" >Create Image</a><a href="load-and-display-image.html" >Load and Display Image</a><a href="pointillism.html" >Pointillism</a><a href="request-image.html" >Request Image</a><a href="transparency.html" >Transparency</a></div><div class="category"><div class="category-title">Input</div><a href="clock.html" >Clock</a><a href="constrain.html" >Constrain</a><a href="easing.html" >Easing</a><a href="keyboard.html" >Keyboard</a><a href="keyboard-functions.html" >Keyboard Functions</a><a href="milliseconds.html" >Milliseconds</a><a href="mouse-1d.html" >Mouse 1D</a><a href="mouse-2d.html" >Mouse 2D</a><a href="mouse-functions.html" >Mouse Functions</a><a href="mouse-press.html" >Mouse Press</a><a href="mouse-signals.html" >Mouse Signals</a><a href="storing-input.html" >Storing Input</a></div><div class="category"><div class="category-title">Lights</div><a href="directional.html" >Directional</a><a href="mixture.html" >Mixture</a><a href="mixture-grid.html" >Mixture Grid</a><a href="on-off.html" >On Off</a><a href="reflection.html" >Reflection</a><a href="spot.html" >Spot</a></div><div class="category"><div class="category-title">Math</div><a href="additive-wave.html" >Additive Wave</a><a href="arctangent.html" >Arctangent</a><a href="distance-1d.html" >Distance 1D</a><a href="distance-2d.html" >Distance 2D</a><a href="double-random.html" >Double Random</a><a href="graphing-2d-equations.html" >Graphing 2D Equations</a><a href="increment-decrement.html" >Increment Decrement</a><a href="linear-interpolation.html" >Linear Interpolation</a><a href="noise-1d.html" >Noise 1D</a><a href="noise-2d.html" >Noise 2D</a><a href="noise-3d.html" >Noise 3D</a><a href="noise-wave.html" >Noise Wave</a><a href="operator-precedence.html" >Operator Precedence</a><a href="polar-to-cartesian.html" >Polar to Cartesian</a><a href="random.html" >Random</a><a href="random-gaussian.html" >Random Gaussian</a><a href="sine.html" >Sine</a><a href="sine-cosine.html" >Sine Cosine</a><a href="sine-wave.html" >Sine Wave</a></div><div class="category"><div class="category-title">Objects</div><a href="composite-objects.html" >Composite Objects</a><a href="inheritance.html" >Inheritance</a><a href="multiple-constructors.html" >Multiple Constructors</a><a href="objects.html" >Objects</a></div><div class="category"><div class="category-title">Shape</div><a href="disable-style.html" >Disable Style</a><a href="get-child.html" >Get Child</a><a href="load-and-display-a-shape-illustration.html" >Load and Display a Shape Illustration</a><a href="load-and-display-an-obj-shape.html" >Load and Display an OBJ shape</a><a href="scale-shape-illustration.html" >Scale Shape Illustration</a><a href="shape-vertices.html" >Shape Vertices</a></div><div class="category"><div class="category-title">Structure</div><a href="coordinates.html" >Coordinates</a><a href="create-graphics.html" >Create Graphics</a><a href="functions.html" >Functions</a><a href="loop.html" >Loop</a><a href="no-loop.html" >No Loop</a><a href="recursion.html" >Recursion</a><a href="redraw.html" >Redraw</a><a href="setup-and-draw.html" >Setup and Draw</a><a href="statements-and-comments.html" >Statements and Comments</a><a href="width-and-height.html" >Width and Height</a></div><div class="category"><div class="category-title">Transform</div><a href="arm.html" >Arm</a><a href="rotate.html" >Rotate</a><a href="rotate-1.html" >Rotate 1</a><a href="rotate-push-pop.html" >Rotate Push Pop</a><a href="scale.html" >Scale</a><a href="translate.html" >Translate</a></div><div class="category"><div class="category-title">Typography</div><a href="letters.html" >Letters</a><a href="text-rotation.html" >Text Rotation</a><a href="words.html" >Words</a></div><div class="category"><div class="category-title">Web</div><a href="loading-images.html" >Loading Images</a><a href="loading-urls.html" >Loading URLs</a></div></div><div class="section-header" onclick="toggleSection('topics')"><span>Topics</span><span class="arrow" id="topics-arrow">▾</span></div><div id="topics-section" style="display:block"><div class="category"><div class="category-title">Advanced Data</div><a href="arraylist-of-objects.html" >ArrayList of objects</a><a href="intlist-lottery-example.html" >IntList Lottery example</a><a href="loading-json-data.html" >Loading JSON Data</a><a href="loading-tabular-data.html" >Loading Tabular Data</a></div><div class="category"><div class="category-title">Animation</div><a href="animated-sprite.html" >Animated Sprite</a><a href="sequential.html" >Sequential</a></div><div class="category"><div class="category-title">Cellular Automata</div><a href="game-of-life.html" >Game Of Life</a><a href="wolfram.html" >Wolfram</a></div><div class="category"><div class="category-title">Drawing</div><a href="continuous-lines.html" >Continuous Lines</a><a href="pattern.html" >Pattern</a><a href="pulses.html" >Pulses</a></div><div class="category"><div class="category-title">File Io</div><a href="load-file1.html" >Load File1</a><a href="load-file2.html" >Load File2</a><a href="save-one-image.html" >Save One Image</a></div><div class="category"><div class="category-title">Fractals And L-Systems</div><a href="koch.html" class="active">Koch</a><a href="mandelbrot.html" >Mandelbrot</a><a href="penrose-snowflake.html" >Penrose Snowflake</a><a href="penrose-tile.html" >Penrose Tile</a><a href="pentigree.html" >Pentigree</a><a href="tree.html" >Tree</a></div><div class="category"><div class="category-title">Gui</div><a href="button.html" >Button</a><a href="handles.html" >Handles</a><a href="rollover.html" >Rollover</a><a href="scrollbar.html" >Scrollbar</a></div><div class="category"><div class="category-title">Image Processing</div><a href="blur.html" >Blur</a><a href="brightness-pixels.html" >Brightness Pixels</a><a href="convolution.html" >Convolution</a><a href="edge-detection.html" >Edge Detection</a><a href="histogram.html" >Histogram</a><a href="pixel-array.html" >Pixel Array</a></div><div class="category"><div class="category-title">Interaction</div><a href="follow1.html" >Follow1</a><a href="follow2.html" >Follow2</a><a href="follow3.html" >Follow3</a><a href="reach1.html" >Reach1</a><a href="reach2.html" >Reach2</a><a href="reach3.html" >Reach3</a><a href="tickle.html" >Tickle</a></div><div class="category"><div class="category-title">Motion</div><a href="bounce.html" >Bounce</a><a href="bouncy-bubbles.html" >Bouncy Bubbles</a><a href="brownian.html" >Brownian</a><a href="circle-collision.html" >Circle Collision</a><a href="linear.html" >Linear</a><a href="morph.html" >Morph</a><a href="moving-on-curves.html" >Moving On Curves</a><a href="reflection1.html" >Reflection1</a><a href="reflection2.html" >Reflection2</a></div><div class="category"><div class="category-title">Simulate</div><a href="flocking.html" >Flocking</a><a href="forces-with-vectors.html" >Forces With Vectors</a><a href="multiple-particle-systems.html" >Multiple Particle Systems</a><a href="simple-particle-system.html" >Simple Particle System</a><a href="smoke-particle-system.html" >Smoke Particle System</a></div><div class="category"><div class="category-title">Vectors</div><a href="acceleration-with-vectors.html" >Acceleration With Vectors</a><a href="bouncing-ball.html" >Bouncing Ball</a><a href="vector-math.html" >Vector Math</a></div></div></div>
</div>
<div class="content">
<h1>Koch</h1>
<div class="preview-wrap" style="aspect-ratio:640/360;max-width:640px;"><iframe id="sketch-frame" width="640" height="360" style="width:100%;height:100%;"></iframe></div>
<script>(function(){const iframe=document.getElementById('sketch-frame');const doc=iframe.contentDocument||iframe.contentWindow.document;doc.open();doc.write(`<!DOCTYPE html><html><head><style>*{margin:0;padding:0;}body{overflow:hidden;}</style><script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"><\/script></head><body><script>// Koch Curve
// A class to describe one line segment in the fractal
// Includes methods to calculate midPVectors along the line according to the Koch algorithm
class KochLine {
constructor(start, end) {
this.a = start.copy();
this.b = end.copy();
}
display() {
stroke(255);
line(this.a.x, this.a.y, this.b.x, this.b.y);
}
start() {
return this.a.copy();
}
end() {
return this.b.copy();
}
// This is easy, just 1/3 of the way
kochleft() {
let v = p5.Vector.sub(this.b, this.a);
v.div(3);
v.add(this.a);
return v;
}
// More complicated, have to use a little trig to figure out where this PVector is!
kochmiddle() {
let v = p5.Vector.sub(this.b, this.a);
v.div(3);
let p = this.a.copy();
p.add(v);
v.rotate(-radians(60));
p.add(v);
return p;
}
// Easy, just 2/3 of the way
kochright() {
let v = p5.Vector.sub(this.a, this.b);
v.div(3);
v.add(this.b);
return v;
}
}
// Koch Curve
// A class to manage the list of line segments in the snowflake pattern
class KochFractal {
constructor() {
this.start = createVector(0, height - 20);
this.end = createVector(width, height - 20);
this.count = 0;
this.lines = [];
this.restart();
}
nextLevel() {
// For every line that is in the array
// create 4 more lines in a new array
this.lines = this.iterate(this.lines);
this.count++;
}
restart() {
this.count = 0; // Reset count
this.lines = []; // Empty the array
this.lines.push(new KochLine(this.start, this.end)); // Add the initial line
}
getCount() {
return this.count;
}
// This is easy, just draw all the lines
render() {
for (let l of this.lines) {
l.display();
}
}
// This is where the **MAGIC** happens
// Step 1: Create an empty array
// Step 2: For every line currently in the array
// - calculate 4 line segments based on Koch algorithm
// - add all 4 line segments into the new array
// Step 3: Return the new array and it becomes the list of line segments for the structure
// As we do this over and over again, each line gets broken into 4 lines,
// which gets broken into 4 lines, and so on. . .
iterate(before) {
let now = []; // Create empty list
for (let l of before) {
// Calculate 5 koch PVectors (done for us by the line object)
let a = l.start();
let b = l.kochleft();
let c = l.kochmiddle();
let d = l.kochright();
let e = l.end();
// Make line segments between all the PVectors and add them
now.push(new KochLine(a, b));
now.push(new KochLine(b, c));
now.push(new KochLine(c, d));
now.push(new KochLine(d, e));
}
return now;
}
}
let k;
function setup() {
createCanvas(640, 360);
frameRate(1); // Animate slowly
k = new KochFractal();
}
function draw() {
background(0);
// Draws the snowflake!
k.render();
// Iterate
k.nextLevel();
// Let's not do it more than 5 times. . .
if (k.getCount() > 5) {
k.restart();
}
}<\/script></body></html>`);doc.close();})();</script>
<div class="code-block">
<div class="code-header">
<span>koch.pde</span>
<button class="copy-btn" onclick="copyCode()">Copy</button>
</div>
<pre id="code-pre">/**
* Koch Curve
* by Daniel Shiffman.
*
* Renders a simple fractal, the Koch snowflake.
* Each recursive level is drawn in sequence.
*/
// Koch Curve
// A class to describe one line segment in the fractal
// Includes methods to calculate midPVectors along the line according to the Koch algorithm
struct KochLine {
// Two PVectors,
// a is the "left" PVector and
// b is the "right" PVector
PVector a;
PVector b;
KochLine(PVector start, PVector end) {
a = start.copy();
b = end.copy();
}
void display() {
stroke(255);
line(a.x, a.y, b.x, b.y);
}
PVector start() {
return a.copy();
}
PVector end() {
return b.copy();
}
// This is easy, just 1/3 of the way
PVector kochleft() {
PVector v = PVector::sub(b, a);
v.div(3);
v.add(a);
return v;
}
// More complicated, have to use a little trig to figure out where this PVector is!
PVector kochmiddle() {
PVector v = PVector::sub(b, a);
v.div(3);
PVector p = a.copy();
p.add(v);
v.rotate(-radians(60));
p.add(v);
return p;
}
// Easy, just 2/3 of the way
PVector kochright() {
PVector v = PVector::sub(a, b);
v.div(3);
v.add(b);
return v;
}
};
// Koch Curve
// A class to manage the list of line segments in the snowflake pattern
struct KochFractal {
PVector start; // A PVector for the start
PVector end; // A PVector for the end
std::vector<KochLine> lines; // A list to keep track of all the lines
int count;
KochFractal() {
start = PVector(0, height - 20);
end = PVector(width, height - 20);
count = 0;
restart();
}
void nextLevel() {
// For every line that is in the vector
// create 4 more lines in a new vector
lines = iterate(lines);
count++;
}
void restart() {
count = 0; // Reset count
lines.clear(); // Empty the vector
lines.push_back(KochLine(start, end)); // Add the initial line
}
int getCount() {
return count;
}
// This is easy, just draw all the lines
void render() {
for (KochLine& l : lines) {
l.display();
}
}
// This is where the **MAGIC** happens
// Step 1: Create an empty vector
// Step 2: For every line currently in the vector
// - calculate 4 line segments based on Koch algorithm
// - add all 4 line segments into the new vector
// Step 3: Return the new vector and it becomes the list of line segments for the structure
// As we do this over and over again, each line gets broken into 4 lines,
// which gets broken into 4 lines, and so on. . .
std::vector<KochLine> iterate(std::vector<KochLine>& before) {
std::vector<KochLine> now; // Create empty list
for (KochLine& l : before) {
// Calculate 5 koch PVectors (done for us by the line object)
PVector a = l.start();
PVector b = l.kochleft();
PVector c = l.kochmiddle();
PVector d = l.kochright();
PVector e = l.end();
// Make line segments between all the PVectors and add them
now.push_back(KochLine(a, b));
now.push_back(KochLine(b, c));
now.push_back(KochLine(c, d));
now.push_back(KochLine(d, e));
}
return now;
}
};
KochFractal k;
void setup() {
size(640, 360);
frameRate(1); // Animate slowly
k = KochFractal();
}
void draw() {
background(0);
// Draws the snowflake!
k.render();
// Iterate
k.nextLevel();
// Let's not do it more than 5 times. . .
if (k.getCount() > 5) {
k.restart();
}
}
</pre>
</div>
</div>
</div>
<footer>
<p>C++ Mode for Processing</p>
<p class="footer-contact">
<span class="footer-sep">·</span>
<a href="https://discord.gg/vShSrPegJT">Discord</a>
</p>
</footer>
<script>function copyCode() {
navigator.clipboard.writeText(document.getElementById('code-pre').innerText).then(() => {
const btn = document.querySelector('.copy-btn');
btn.textContent = 'Copied!'; btn.classList.add('copied');
setTimeout(() => { btn.textContent = 'Copy'; btn.classList.remove('copied'); }, 2000);
});
}
function toggleSection(name) {
const sec = document.getElementById(name+'-section');
const arrow = document.getElementById(name+'-arrow');
const open = sec.style.display !== 'none';
sec.style.display = open ? 'none' : 'block';
arrow.textContent = open ? '▸' : '▾';
}</script>
<script src="../assets/nav.js"></script>
</body>
</html>