103 lines
2.4 KiB
Go
103 lines
2.4 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"strconv"
|
||
|
|
||
|
"github.com/lucasb-eyer/go-colorful"
|
||
|
)
|
||
|
|
||
|
type Mandelbrot []uint
|
||
|
|
||
|
func (m Mandelbrot) SetPixel(width int, x int, y int, color []uint) {
|
||
|
start := y*int(width)*4 + x*4
|
||
|
for i := 0; i < 4; i++ {
|
||
|
m[start+i] = color[i]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func GetColor(iteration uint, maxIterations uint) []uint {
|
||
|
c := colorful.Hsl(float64(iteration)/256, 1.0, float64(iteration)/(float64(iteration)+8.0))
|
||
|
return []uint{
|
||
|
uint(c.R * 255),
|
||
|
uint(c.G * 255),
|
||
|
uint(c.B * 255),
|
||
|
255,
|
||
|
}
|
||
|
//return []uint{0, 0, 0, 255}
|
||
|
}
|
||
|
|
||
|
func CalculateMandelbrot(maxIterations uint, minX float64, minY float64, maxX float64, maxY float64, width int, height int) Mandelbrot {
|
||
|
mandelbrot := make(Mandelbrot, width*height*4)
|
||
|
|
||
|
dx := maxX - minX
|
||
|
dy := maxY - minY
|
||
|
for row := 0; row < height; row++ {
|
||
|
for col := 0; col < width; col++ {
|
||
|
cRe := (float64(col)*dx)/float64(width) + minX
|
||
|
cIm := (float64(row)*dy)/float64(height) + minY
|
||
|
|
||
|
var x float64
|
||
|
var y float64
|
||
|
|
||
|
var iteration uint
|
||
|
for ; x*x+y*y <= 4 && iteration < maxIterations; iteration++ {
|
||
|
newX := x*x - y*y + cRe
|
||
|
y = 2*x*y + cIm
|
||
|
x = newX
|
||
|
}
|
||
|
|
||
|
mandelbrot.SetPixel(width, col, row, GetColor(iteration, maxIterations))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return mandelbrot
|
||
|
}
|
||
|
|
||
|
func GetFloatParameter(query url.Values, name string, defaultValue float64) float64 {
|
||
|
if str := query.Get(name); len(str) > 0 {
|
||
|
value, err := strconv.ParseFloat(str, 64)
|
||
|
if err == nil {
|
||
|
return value
|
||
|
}
|
||
|
}
|
||
|
return defaultValue
|
||
|
}
|
||
|
|
||
|
func GetIntParameter(query url.Values, name string, defaultValue int) int {
|
||
|
if str := query.Get(name); len(str) > 0 {
|
||
|
value, err := strconv.ParseInt(str, 10, 64)
|
||
|
if err == nil {
|
||
|
return int(value)
|
||
|
}
|
||
|
}
|
||
|
return defaultValue
|
||
|
}
|
||
|
|
||
|
func MainHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||
|
|
||
|
query := r.URL.Query()
|
||
|
|
||
|
var maxIterations uint = 1000
|
||
|
minX := GetFloatParameter(query, "minX", -2.0)
|
||
|
minY := GetFloatParameter(query, "minY", -2.0)
|
||
|
maxX := GetFloatParameter(query, "maxX", 2.0)
|
||
|
maxY := GetFloatParameter(query, "maxY", 2.0)
|
||
|
width := GetIntParameter(query, "width", 1000)
|
||
|
height := GetIntParameter(query, "height", 1000)
|
||
|
|
||
|
log.Println(minX, minY, maxX, maxY, width, height)
|
||
|
|
||
|
json.NewEncoder(w).Encode(CalculateMandelbrot(maxIterations, minX, minY, maxX, maxY, width, height))
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
http.HandleFunc("/", MainHandler)
|
||
|
|
||
|
log.Fatal(http.ListenAndServe(":8001", nil))
|
||
|
}
|