Skip to content

Commit cccaeb7

Browse files
authored
Merge pull request #20814 from Mugen87/dev44
GeometryUtils: Add gosper curve generator.
2 parents 65b712a + 5a13794 commit cccaeb7

File tree

4 files changed

+199
-92
lines changed

4 files changed

+199
-92
lines changed

examples/js/utils/GeometryUtils.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,104 @@ THREE.GeometryUtils = {
140140
// Return complete Hilbert Curve.
141141
return vec;
142142

143+
},
144+
145+
/**
146+
* Generates a Gosper curve (lying in the XY plane)
147+
*
148+
* https://gist.github.com/nitaku/6521802
149+
*
150+
* @param size The size of a single gosper island.
151+
*/
152+
gosper: function ( size ) {
153+
154+
size = ( size !== undefined ) ? size : 1;
155+
156+
function fractalize( config ) {
157+
158+
var output;
159+
var input = config.axiom;
160+
161+
for ( var i = 0, il = config.steps; 0 <= il ? i < il : i > il; 0 <= il ? i ++ : i -- ) {
162+
163+
output = '';
164+
165+
for ( var j = 0, jl = input.length; j < jl; j ++ ) {
166+
167+
var char = input[ j ];
168+
169+
if ( char in config.rules ) {
170+
171+
output += config.rules[ char ];
172+
173+
} else {
174+
175+
output += char;
176+
177+
}
178+
179+
}
180+
181+
input = output;
182+
183+
}
184+
185+
return output;
186+
187+
}
188+
189+
function toPoints( config ) {
190+
191+
var currX = 0, currY = 0;
192+
var angle = 0;
193+
var path = [ 0, 0, 0 ];
194+
var fractal = config.fractal;
195+
196+
for ( var i = 0, l = fractal.length; i < l; i ++ ) {
197+
198+
var char = fractal[ i ];
199+
200+
if ( char === '+' ) {
201+
202+
angle += config.angle;
203+
204+
} else if ( char === '-' ) {
205+
206+
angle -= config.angle;
207+
208+
} else if ( char === 'F' ) {
209+
210+
currX += config.size * Math.cos( angle );
211+
currY += - config.size * Math.sin( angle );
212+
path.push( currX, currY, 0 );
213+
214+
}
215+
216+
}
217+
218+
return path;
219+
220+
}
221+
222+
//
223+
224+
var gosper = fractalize( {
225+
axiom: 'A',
226+
steps: 4,
227+
rules: {
228+
A: 'A+BF++BF-FA--FAFA-BF+',
229+
B: '-FA+BFBF++BF+FA--FA-B'
230+
}
231+
} );
232+
233+
var points = toPoints( {
234+
fractal: gosper,
235+
size: size,
236+
angle: Math.PI / 3 // 60 degrees
237+
} );
238+
239+
return points;
240+
143241
}
144242

145243
};

examples/jsm/utils/GeometryUtils.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import {
55
export namespace GeometryUtils {
66
export function hilbert2D( center?: Vector3, size?: number, iterations?: number, v0?: number, v1?: number, v2?: number, v3?: number ): Vector3[];
77
export function hilbert3D( center?: Vector3, size?: number, iterations?: number, v0?: number, v1?: number, v2?: number, v3?: number, v4?: number, v5?: number, v6?: number, v7?: number ): Vector3[];
8+
export function gosper( size?: number ): number[];
89
}

examples/jsm/utils/GeometryUtils.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,104 @@ var GeometryUtils = {
144144
// Return complete Hilbert Curve.
145145
return vec;
146146

147+
},
148+
149+
/**
150+
* Generates a Gosper curve (lying in the XY plane)
151+
*
152+
* https://gist.github.com/nitaku/6521802
153+
*
154+
* @param size The size of a single gosper island.
155+
*/
156+
gosper: function ( size ) {
157+
158+
size = ( size !== undefined ) ? size : 1;
159+
160+
function fractalize( config ) {
161+
162+
var output;
163+
var input = config.axiom;
164+
165+
for ( var i = 0, il = config.steps; 0 <= il ? i < il : i > il; 0 <= il ? i ++ : i -- ) {
166+
167+
output = '';
168+
169+
for ( var j = 0, jl = input.length; j < jl; j ++ ) {
170+
171+
var char = input[ j ];
172+
173+
if ( char in config.rules ) {
174+
175+
output += config.rules[ char ];
176+
177+
} else {
178+
179+
output += char;
180+
181+
}
182+
183+
}
184+
185+
input = output;
186+
187+
}
188+
189+
return output;
190+
191+
}
192+
193+
function toPoints( config ) {
194+
195+
var currX = 0, currY = 0;
196+
var angle = 0;
197+
var path = [ 0, 0, 0 ];
198+
var fractal = config.fractal;
199+
200+
for ( var i = 0, l = fractal.length; i < l; i ++ ) {
201+
202+
var char = fractal[ i ];
203+
204+
if ( char === '+' ) {
205+
206+
angle += config.angle;
207+
208+
} else if ( char === '-' ) {
209+
210+
angle -= config.angle;
211+
212+
} else if ( char === 'F' ) {
213+
214+
currX += config.size * Math.cos( angle );
215+
currY += - config.size * Math.sin( angle );
216+
path.push( currX, currY, 0 );
217+
218+
}
219+
220+
}
221+
222+
return path;
223+
224+
}
225+
226+
//
227+
228+
var gosper = fractalize( {
229+
axiom: 'A',
230+
steps: 4,
231+
rules: {
232+
A: 'A+BF++BF-FA--FAFA-BF+',
233+
B: '-FA+BFBF++BF+FA--FA-B'
234+
}
235+
} );
236+
237+
var points = toPoints( {
238+
fractal: gosper,
239+
size: size,
240+
angle: Math.PI / 3 // 60 degrees
241+
} );
242+
243+
return points;
244+
147245
}
148246

149247
};

examples/webgl_framebuffer_texture.html

Lines changed: 2 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import * as THREE from '../build/three.module.js';
4141

4242
import { OrbitControls } from './jsm/controls/OrbitControls.js';
43+
import { GeometryUtils } from './jsm/utils/GeometryUtils.js';
4344

4445
let camera, scene, renderer;
4546
let line, sprite, texture;
@@ -75,7 +76,7 @@
7576

7677
//
7778

78-
const points = generatePoints();
79+
const points = GeometryUtils.gosper( 8 );
7980

8081
const geometry = new THREE.BufferGeometry();
8182
const positionAttribute = new THREE.Float32BufferAttribute( points, 3 );
@@ -206,97 +207,6 @@
206207

207208
}
208209

209-
//
210-
211-
function generatePoints() {
212-
213-
// generate gosper curve (from https://gist.github.com/nitaku/6521802)
214-
215-
const gosper = fractalize( {
216-
axiom: 'A',
217-
steps: 4,
218-
rules: {
219-
A: 'A+BF++BF-FA--FAFA-BF+',
220-
B: '-FA+BFBF++BF+FA--FA-B'
221-
}
222-
} );
223-
224-
const points = toPoints( {
225-
fractal: gosper,
226-
side: 8,
227-
angle: Math.PI / 3
228-
} );
229-
230-
return points;
231-
232-
}
233-
234-
function fractalize( config ) {
235-
236-
let output;
237-
let input = config.axiom;
238-
239-
for ( let i = 0, il = config.steps; 0 <= il ? i < il : i > il; 0 <= il ? i ++ : i -- ) {
240-
241-
output = '';
242-
243-
for ( let j = 0, jl = input.length; j < jl; j ++ ) {
244-
245-
const char = input[ j ];
246-
247-
if ( char in config.rules ) {
248-
249-
output += config.rules[ char ];
250-
251-
} else {
252-
253-
output += char;
254-
255-
}
256-
257-
}
258-
259-
input = output;
260-
261-
}
262-
263-
return output;
264-
265-
}
266-
267-
function toPoints( config ) {
268-
269-
let currX = 0, currY = 0;
270-
let angle = 0;
271-
const path = [ 0, 0, 0 ];
272-
const fractal = config.fractal;
273-
274-
for ( let i = 0, l = fractal.length; i < l; i ++ ) {
275-
276-
const char = fractal[ i ];
277-
278-
if ( char === '+' ) {
279-
280-
angle += config.angle;
281-
282-
} else if ( char === '-' ) {
283-
284-
angle -= config.angle;
285-
286-
} else if ( char === 'F' ) {
287-
288-
currX += config.side * Math.cos( angle );
289-
currY += - config.side * Math.sin( angle );
290-
path.push( currX, currY, 0 );
291-
292-
}
293-
294-
}
295-
296-
return path;
297-
298-
}
299-
300210
</script>
301211

302212
</body>

0 commit comments

Comments
 (0)