Add web sub project
This commit is contained in:
parent
818cd906ac
commit
1d3581370a
114
web/render.go
Normal file
114
web/render.go
Normal 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
64
web/web.go
Normal 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>`)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user