### JavaScript/Canvas 3D Map generator

This takes some math functions and uses JavaScript and canvas to draw a 3D map. It was created for an assignment on algorithms to traverse maps to find the highest point; a way to generate a varied set of maps with a set of points was needed, but Google didn't turn anything up.
Also JavaScript's functional nature suits the problem very nicely.

Canvas is required, so Internet Explorer won't work with this page (until IE9 at least). Also generating, manipulating and drawing 200*200 points comes with a delay even on the best computers.

In a nutshell: Enter JavaScript code which returns an (x,y)->z function, hit Run, it'll be drawn.

Input data:

#### Output:

Your browser does not support canvas.

#### Predefined

Click any of these pre-defined example maps to load them above.

```// Simple hill
var fd=shrink(translate(-30,50,toCartesian(function(r,t){return r;})));
return function(x,y){ return 2*(1-fd(x,y)); };
```
```// Large hills
var fa=shrink(rotate(Math.PI/5, zoom(5,function(x,y){return Math.sin(x)*Math.cos(y);})));
var fd=shrink(translate(-30,-40,toCartesian(function(r,t){return r
;})));
return function(x,y){ return 2*(1-fd(x,y))+fa(x,y); };
```
```// Small hills
var fa=shrink(rotate(Math.PI/7, zoom(1.5, function(x,y){return Math.sin(x)*Math.cos(y);})));
var fd=shrink(translate(-50,30,toCartesian(function(r,t){return r;})));
return function(x,y){ return 2*(1-fd(x,y))+fa(x,y); };
```
```// Large ripples
var fa=shrink(translate(40,40,toCartesian(function(r,t){return r;})));
var fd=shrink(zoom(1.5, toCartesian(function(r,t){return Math.sin(r);})));
return function(x,y){ return fd(x,y)+2*(1-fa(x,y)); };
```
```// Small ripples
var fa=shrink(translate(-25,15,toCartesian(function(r,t){return r;})));
var fd=shrink(zoom(0.5, toCartesian(function(r,t){ return Math.sin(r); })));
return function(x,y){ return fd(x,y)+2*(1-fa(x,y)); };
```
```// Large ripples with radial spokes
var fa=shrink(translate(40,40,toCartesian(function(r,t){return r;})));
var fd=shrink(zoom(1.5, toCartesian(function(r,t){return Math.sin(r);})));
var fc=shrink(toCartesian(function(r,t){return Math.sin(t*20);}));
return function(x,y){ return fd(x,y)+2*(1-fa(x,y))+fc(x,y)/2; };
```
```// Small ripples with radial spokes
var fa=shrink(translate(-25,15,toCartesian(function(r,t){return r;})));
var fd=shrink(zoom(0.5, toCartesian(function(r,t){return Math.sin(r);})));
var fc=shrink(toCartesian(function(r,t){return Math.sin(t*20);}));
return function(x,y){ return fd(x,y)+2*(1-fa(x,y))+fc(x,y)/2; };
```
```// Small layered circular plateaus
var cycleLength=6;
var a=shrink(toCartesian(function(r,t){
var lastPlateau = r - (r % cycleLength);
if( lastPlateau <= r && r < lastPlateau+(cycleLength/2) ) return lastPlateau;
else return lastPlateau+cycleLength*(-Math.cos(Math.PI*(r%(cycleLength/2))/(cycleLength/2))+1)/2;
}
));
return function(x,y) { return (1-a(x,y)); };
```
```// Large layered circular plateaus
var cycleLength=14;
var a=shrink(toCartesian(function(r,t){
var lastPlateau = r - (r % cycleLength);
if( lastPlateau <= r && r < lastPlateau+(cycleLength/2) ) return lastPlateau;
else return lastPlateau+cycleLength*(-Math.cos(Math.PI*(r%(cycleLength/2))/(cycleLength/2))+1)/2;
}
));
return function(x,y) { return (1-a(x,y)); };
```
```// Default
return function(x,y){ return x+y; };
```

Enter some JavaScript which returns a function(x,y)->z , domain x=-100 to 100, y=-100 to 100
The following helper functions are available:

• zoom(zoomBy, func(x,y)) - Returns a function(x,y) which is "zoomed into" (scaled up).
If X is zoomed by 2 the value that was at X=15,y=20 will now be at X=30,Y=40.
• rotate(rotateBy, func(x,y)) - Returns a function(x,y) rotated clockwise by rotateBy radians.
If rotated by Math.PI/2 the point at X=100,Y=0 will be drawn at X=0,Y=100.
• translate(translateX, translateY, func(x,y)) - Returns a function(x,y) shifted by the given X/Y values.
If translated by 10,20 the value that was at X=0,Y=0 will now be at X=10,Y=20.