In a world made small and accessible by technology, it is easy to forget the magnitude of nature’s infinite complexity. But sometimes technology reminds us, such as when trawling planet Earth on Google’s Satellite View, zooming across landscapes partitioned by natural and unnatural boundaries.

While searching Google Earth, Paul Bourke, a research associate professor at the University of Western Australia, discovered an amazing sight—the patterns of the Earth seemed to form a delicate geometric pattern when viewed from the sky. Not only delicate, but almost perfect. Bourke was captivated by the geography—lacy tracks of rivers and mountain ranges stretching across the Earth in unison as if digitally cloned.

Fractals are recognized as patterns of self-similarity over varying degrees of scale. There are both mathematical fractals as well as natural fractals—the former are idealized and found across a range of scales, while the latter generally only exist across a smaller scale range.

Bourke explains that fractals are found in all parts of life, from the brain sciences and astrophysics to geographic formations and riverbeds. “Fractal and chaotic processes are the norm, not the exception.”

“I always knew these amazing natural patterns would be there,” he said. “They are literally everywhere—it’s just a matter of finding them.”

And find them he did. Bourke, an authority on fractals and visualizations, showcases more than 40 different fractals he’s uncovered while zooming through the satellite views of 25 countries. Through his website, he encourages users to submit examples they’ve found in their own browsing, and provides KMZ coordinate files for each image, allowing users to visit the exact views of the fractal features. Bourke’s collection realizes the power enabled by the open-ended tools of modern technology and applies them to a practical and popular aesthetic end.

*To see more natural fractal patterns, visit Bourke’s website.*

- Alaska
- Alec Soth
- Alec Soth
- Australia
- Austria
- China
- Digital art
- Dimension
- earth
- Egypt
- Fractal
- Fractal
- Fractals
- Google Earth
- Greenland
- Landscape
- Lord Soth
- Malaysia
- Man on the Wire
- Mathematical analysis
- Mathematics
- Mexico
- Namibia
- Norway
- pattern
- Paul Bourke
- Russia
- satellite views
- Science
- Self-similarity
- space
- Spain
- Topology
- University of Western Australia
- Western Australia
- Western Australia

While experimenting with ways to calculate organic mesh surfaces I’ve tried to avoid 3D Bezier patches, since setting up control points programmatically is a bit of a pain. 2D is bad enough. But, as so often happens, I’ve found myself in a situation where I need a structure that is best described as a Bezier patch.

Paul Bourke comes to the rescue with sample code written in C, which took all of 5 minutes to port to Processing. The code below is all Bourke’s apart from the rendering logic. If you don’t know his depository of miscellaneous geometry code and wisdom, run and have a look. It’s proven invaluable over the years.

An applet version of this sketch can be seen on OpenProcessing.org.

Code: bezPatch.pde

// bezPatch.pde by Marius Watz // Direct port of sample code by Paul Bourke. // Original code: http://paulbourke.net/geometry/bezier/ int ni=4, nj=5, RESI=ni*10, RESJ=nj*10; PVector outp[][], inp[][]; void setup() { size(600,600,P3D); build(); smooth(); } void draw() { background(255); translate(width/2,height/2); lights(); scale(0.9); rotateY(map(mouseX,0,width,-PI,PI)); rotateX(map(mouseY,0,height,-PI,PI)); noStroke(); fill(255); stroke(0); for(int i=0; i<RESI-1; i++) { beginShape(QUAD_STRIP); for(int j=0; j<RESJ; j++) { vertex(outp[i][j].x,outp[i][j].y,outp[i][j].z); vertex(outp[i+1][j].x,outp[i+1][j].y,outp[i+1][j].z); } endShape(); } } void keyPressed() { if(key==' ') build(); if(!online)saveFrame("bezPatch.png"); } void build() { int i, j, ki, kj; double mui, muj, bi, bj; outp=new PVector[RESI][RESJ]; inp=new PVector[ni+1][nj+1]; for (i=0;i<=ni;i++) { for (j=0;j<=nj;j++) { inp[i][j]=new PVector(i,j,random(-3,3)); } } for (i=0;i<RESI;i++) { mui = i / (double)(RESI-1); for (j=0;j<RESJ;j++) { muj = j / (double)(RESJ-1); outp[i][j]=new PVector(); for (ki=0;ki<=ni;ki++) { bi = BezierBlend(ki, mui, ni); for (kj=0;kj<=nj;kj++) { bj = BezierBlend(kj, muj, nj); outp[i][j].x += (inp[ki][kj].x * bi * bj); outp[i][j].y += (inp[ki][kj].y * bi * bj); outp[i][j].z += (inp[ki][kj].z * bi * bj); } } outp[i][j].add(new PVector(-ni/2,-nj/2,0)); outp[i][j].mult(100); } } } double BezierBlend(int k, double mu, int n) { int nn, kn, nkn; double blend=1; nn = n; kn = k; nkn = n - k; while (nn >= 1) { blend *= nn; nn--; if (kn > 1) { blend /= (double)kn; kn--; } if (nkn > 1) { blend /= (double)nkn; nkn--; } } if (k > 0) blend *= Math.pow(mu, (double)k); if (n-k > 0) blend *= Math.pow(1-mu, (double)(n-k)); return(blend); }