Add web sub project

This commit is contained in:
Steven Polley 2018-07-30 22:41:10 -06:00
parent 818cd906ac
commit 1d3581370a
2 changed files with 178 additions and 0 deletions

114
web/render.go Normal file
View File

@ -0,0 +1,114 @@
package main
import (
"image"
"image/color"
"image/png"
"log"
"math/cmplx"
"net/http"
"runtime"
"strconv"
"strings"
"sync"
)
const (
Size = 256
Iterations = (1<<16 - 1) / Brighten
Brighten = 1024
)
func mandelbrot(c complex128) uint16 {
var z complex128
for i := 0; i < Iterations; i++ {
z = z*z + c
if cmplx.IsNaN(z) {
return uint16(i)
}
}
return Iterations
}
type pixel struct {
out *image.Gray16
x, y int
tileX, tileY int64
tileZoom uint8
wg *sync.WaitGroup
}
var queue = make(chan pixel)
func computeThread() {
for p := range queue {
val := mandelbrot(
complex(
(float64(p.x)/Size+float64(p.tileX))/float64(uint(1<<p.tileZoom)),
(float64(p.y)/Size+float64(p.tileY))/float64(uint(1<<p.tileZoom)),
),
)
p.out.SetGray16(p.x, p.y, color.Gray16{val * Brighten})
p.wg.Done()
}
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
for i := 0; i < runtime.GOMAXPROCS(0); i++ {
go computeThread()
}
log.Fatal(http.ListenAndServe(":6161", nil))
}
func renderTile(w http.ResponseWriter, r *http.Request) {
components := strings.Split(r.URL.Path, "/")[1:]
if len(components) != 4 || components[0] != "mandelbrot" || components[3][len(components[3])-4:] != ".png" {
w.WriteHeader(http.StatusNotFound)
return
}
components[3] = components[3][:len(components[3])-4]
tileX, err := strconv.ParseInt(components[2], 10, 64)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
tileY, err := strconv.ParseInt(components[3], 10, 64)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
tileZoom, err := strconv.ParseUint(components[1], 10, 8)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
var wg sync.WaitGroup
wg.Add(Size * Size)
img := image.NewGray16(image.Rect(0, 0, Size, Size))
for x := 0; x < Size; x++ {
for y := 0; y < Size; y++ {
queue <- pixel{img, x, y, tileX, tileY, uint8(tileZoom), &wg}
}
}
wg.Wait()
w.Header().Set("Content-Type", "image/png")
png.Encode(w, img)
}
func init() {
http.HandleFunc("/mandelbrot/", renderTile)
}

64
web/web.go Normal file
View File

@ -0,0 +1,64 @@
package main
import (
"fmt"
"net/http"
)
func init() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
w.Header().Set("Location", "/")
w.WriteHeader(http.StatusMovedPermanently)
return
}
fmt.Fprintf(w, `<!DOCTYPE html>
<html>
<head>
<title>Mandelbrot Map</title>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script>
var mandelbrotTypeOptions = {
getTileUrl: function(coord, zoom) {
return '/mandelbrot/' + zoom + '/' + coord.x + '/' + coord.y + '.png';
},
tileSize: new google.maps.Size(256, 256),
maxZoom: (1<<8) - 1,
minZoom: 0,
name: 'Mandelbrot'
};
var mandelbrotMapType = new google.maps.ImageMapType(mandelbrotTypeOptions);
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(0, 0),
zoom: 1,
streetViewControl: false,
mapTypeControlOptions: {
mapTypeIds: ['mandelbrot']
}
};
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
map.mapTypes.set('mandelbrot', mandelbrotMapType);
map.setMapTypeId('mandelbrot');
}
</script>
<style>
#map_canvas {
position: absolute !important;
left: 0 !important;
right: 0 !important;
top: 0 !important;
bottom: 0 !important;
}
</style>
</head>
<body onload="initialize()">
<div id="map_canvas"></div>
</body>
</html>`)
})
}