venerdì 25 febbraio 2022

Quadtree in Go

metto questo abbozzo di codice perche', nonostante non funzionante, puo' essere interessante

Ai tempi di Fractint su Dos c'e un algoritmo che divideva il piano di quadrati, se i punti estremi del quadrato avevano lo stesso valore allora tutto il quadrato assumeva lo stesso colore dell'insieme di Mandelbrot, in caso contrario il quadrato veniva a sua volta diviso in 4 quadrati e si reiterava

In questo caso ho cercato di fare lo stesso usando le goroutine  ed la ricorsione


package main

import (
    "fmt"
    "math"
    "math/cmplx"
    "reflect"
    "strconv"
    "sync"

    "github.com/fogleman/gg"
)

var wg sync.WaitGroup

// ATTENZION    E il nome delle variabili deve essere in uppercase
// per poter esportare la variabile e
type punto struct {
    Min_x float64
    Max_x float64
    Min_y float64
    Max_y float64
    Itera int64
}

var punti []punto // slice di struct
var transi punto
var mu sync.Mutex

func calcola(a float64, b float64) int {
    var k int
    c := complex(a, b)
    k = 0

    x := complex(0.0, 0.0)
    for k = 0; k < 25; k++ {
        x_a := (x * x)
        x_a = x_a + c
        x = x_a
        if cmplx.Abs(x) > 2 {
            return k
        }
    }
    return k
}

func dividi(min_x float64, max_x float64, min_y float64, max_y float64) {
    defer wg.Done()

    x1 := calcola(min_x, min_y)
    x2 := calcola(max_x, max_y)

    if (x1 != x2) && (max_x-min_x > 0.005) {

        mezzo_x := (max_x - min_x) / 2
        mezzo_y := (max_y - min_y) / 2
        wg.Add(4)
        go dividi(min_x, min_x+mezzo_x, min_y, min_y+mezzo_y)
        go dividi(min_x+mezzo_x, max_x, min_y, min_y+mezzo_y)
        go dividi(min_x, min_x+mezzo_x, min_y+mezzo_y, max_y)
        go dividi(min_x+mezzo_x, max_x, min_y+mezzo_y, max_y)

    } else {
        fmt.Println(strconv.FormatFloat(min_x, 'f', 6, 32) + ";" + strconv.FormatFloat(min_y, 'f', 6, 32) + ";" + strconv.Itoa(x1))

        s := reflect.ValueOf(&transi).Elem()
        s.Field(0).SetFloat(min_x)
        s.Field(1).SetFloat(max_x)
        s.Field(2).SetFloat(min_y)
        s.Field(3).SetFloat(max_y)
        s.Field(4).SetInt(int64(x1))

        mu.Lock()
        punti = append(punti, transi)
        mu.Unlock()
    }

}

func grafica() {
    dc := gg.NewContext(400, 400)

    dx := 3.0 / 400
    dy := 2.0 / 400

    for _, value := range punti {
        fmt.Printf("%d\n", value)
        min_x := math.Round(value.Min_x*dx) + 200
        max_x := math.Round(value.Max_x*dx) + 200
        min_y := math.Round((value.Min_y * dy)) + 200
        max_y := math.Round((value.Max_y * dy)) + 200
        dc.DrawRectangle(min_x, max_x, min_y, max_y)
        dc.SetRGB255(value.Itera, 0, 0)
        dc.Fill()

    }

    dc.SavePNG("mandelbrot.png")
}

func main() {
    wg.Add(1)
    go dividi(-2.0, 1.0, -1.0, 1.0)
    wg.Wait()
    grafica()
}

Nessun commento:

Posta un commento

Dockerizza Flask

Un esempio semplice per inserire in un container Docker una applicazione Flask Partiamo da una semplice applicazione che ha un file app.py ...