💾 Archived View for thrig.me › art › orbits › squareorbit.go captured on 2024-08-31 at 14:18:05.

View Raw

More Information

⬅️ Previous capture (2023-05-24)

-=-=-=-=-=-=-

// orbits of colored squares

package main

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"image/gif"
	"log"
	"math"
	"math/rand"
	"os"
	"time"
)

type Orbit struct {
	a float64
	b float64

	afuzz float64
	bfuzz float64

	xmid int
	ymid int

	iters int
}

var palette = []color.Color{
	color.White,
	color.Black,
	color.NRGBA{255, 114, 114, 255},
	color.NRGBA{255, 203, 114, 255},
	color.NRGBA{255, 255, 114, 255},
	color.NRGBA{57, 128, 57, 255},
	color.NRGBA{114, 114, 255, 255},
	color.NRGBA{99, 58, 130, 255},
	color.NRGBA{238, 237, 238, 255},

	color.NRGBA{78, 78, 78, 255},
	color.NRGBA{99, 99, 99, 255},
	color.NRGBA{130, 130, 130, 255},
	color.NRGBA{156, 156, 156, 255},
	color.NRGBA{208, 208, 208, 255},
	color.NRGBA{237, 237, 237, 255},
	color.NRGBA{239, 239, 239, 255},
}

const (
	fg_color = 0
	bg_color = 1
	cidx1    = 2
	cidx2    = 3
	cidx3    = 4
	cidx4    = 5
	cidx5    = 6
	cidx6    = 7
	cidx7    = 8
)

func hline(canvas *image.Paletted, cindex uint8, x, y, len int) {
	x2 := x + len
	for nx := x; nx <= x2; nx++ {
		canvas.SetColorIndex(nx, y, cindex)
	}
}

func vline(canvas *image.Paletted, cindex uint8, x, y, len int) {
	y2 := y + len
	for ny := y; ny <= y2; ny++ {
		canvas.SetColorIndex(x, ny, cindex)
	}
}

func irand(max int) int {
	return int(rand.Int63n(int64(max)))
}

func one_in(n int) bool {
	x := rand.Int63n(int64(n))
	if x > 0 {
		return false
	} else {
		return true
	}
}

func make_orbit() Orbit {
	orb := Orbit{
		a: 200 + rand.Float64()*800,

		xmid: irand(1128),
		ymid: irand(752),
	}
	// not too eccentric an orbit? usually.
	if one_in(20) {
		orb.b = 200 + rand.Float64()*800
	} else {
		orb.b = orb.a + rand.Float64()*100.0 + rand.Float64()*100.0 - 100.0
	}
	return orb
}

// square(canvas, x+orb.xmid, y+orb.ymid, uint8(irand(7)+2))
func square(canvas *image.Paletted, x, y int, cindex uint8) {
	// could do x,y as the mid-point but that's a little harder so
	// let's just draw something from given points. also may need a
	// size parameter
	len := 12
	hline(canvas, cindex, x, y, len)
	hline(canvas, cindex, x, y+len, len)
	vline(canvas, cindex, x, y, len)
	vline(canvas, cindex, x+len, y, len)
}

// for 0 <= time <= 2*pi to sketch the whole thing
func xyell(time, a, b float64) (x, y float64) {
	x = a * math.Cos(time)
	y = b * math.Sin(time)
	return x, y
}

func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	with_gif("out.gif")
	fmt.Fprintf(os.Stderr, "ok\n") // KLUGE for "fmt" import
}

func with_gif(file string) {
	out, err := os.Create(file)
	if err != nil {
		log.Fatal(err)
	}
	defer out.Close()

	xsize := 1128
	ysize := 752

	rect := image.Rect(0, 0, xsize, ysize)
	canvas := image.NewPaletted(rect, palette)
	draw.Draw(canvas, canvas.Bounds(), &image.Uniform{palette[bg_color]}, image.ZP, draw.Src)

	done := 0
	for {
		if done == 3 {
			break
		}
		orb := make_orbit()
		var ci uint8 = cidx1
		for t := 0.0; t < 2*math.Pi; t += 0.1 {
			xf, yf := xyell(t, orb.a, orb.b)
			x := int(xf)
			y := int(yf)
			square(canvas, x+orb.xmid, y+orb.ymid, ci)
			ci++
			if ci > cidx7 {
				ci = cidx1
			}
		}
		done++
	}

	options := &gif.Options{
		NumColors: len(palette),
	}
	gif.Encode(out, canvas, options)
}