Add web sub project
This commit is contained in:
		
							
								
								
									
										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>`)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user