gofrac

package module
v0.0.0-...-c162576 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 17, 2020 License: BSD-3-Clause Imports: 12 Imported by: 0

README

gofrac

A simple library for generating fractals.

Julia set

Fractals

It's difficult to pin down a single, authoritative definition of exactly what a fractal is. Self-similarity - though not necessarily repetition - seems to be a central component. We've all seen images of fractals, whether it's a Sierpiński Triangle or the famous Mandelbrot set, either in movies or popular science media.

The primary focus of this library as it currently stands is the production of images generated by repeatedly applying a function to a point in the complex plane. This includes Julia sets and, by extension, the Mandelbrot set. There is also work being done to include a class of generative methods developed by Kalantari and others which have been grouped under the name polynomiography.

Installation

To work with gofrac, you can use Go's package manager to install it by issuing the following command:

go get github.com/cfdwalrus/gofrac

Additionally, you'll need Lucas Beyer's go-colorful package, which can be found here.

Having installed the requisite packages, you can use gofrac in your project simply by including it with an import statement:

import "github.com/cfdwalrus/gofrac"

Using gofrac

For a quick start, see the examples in gofrac_examples.go.

The library has a modular design in which the selection of components determines the output. These components are the class of fractal to be rendered, the domain in which it is to be calculated, the selection and manipulation of resultant quantities for plotting, and a palette consisting of a set of colors coupled with a method by which they are chosen.

For example, in order to produce the classic image of the Mandelbrot set, one would choose the appropriate components. (N.B.: Other classes of fractals are available in the library, and you are free to create your own!)

Choose a class of fractal

The first step is to choose a class of fractal. The Mandelbrot struct implements the complex quadratic equation used to produce it, so we would create an instance of it with an appropriate escape radius - say, 80.0.

m := gofrac.NewMandelbrot(80.0)
Specify a domain

With that determined, the next choice is which points in the complex plane should be rendered. The majority of the Mandelbrot set lies in the rectangle spanned by the points (-2.5, -1.0) and (1.0, 1.0), where the point (a, b) represents a complex number a + bi. Setting the number of samples to be taken along each axis of the bounded area allows gofrac to calculate the points at which it should iteratively apply the Mandelbrot map.

w := 1280
h := 768
d, err := gofrac.NewDomain(-2.5, -1.0, 1.0, 1.0, w, h)
Plot the results

It's time to choose which part(s) of the output are important. For our example, that is the escape time, i.e. how many iterations it took for the modulus of the iterate to exceed the escape radius chosen earlier. Since this happens almost immediately away from the boudary of the set, normalizing the escape times will perhaps yield a more visually interesting result.

plot := gofrac.NormalizedEscapeTimePlotter{}
Add some color

In order to visualize the values produced by the plotter, gofrac uses a color palette. For the purposes of this library, a palette is anything that takes a floating-point value and the maximum number of iterations to be performed before considering a value to have converged. There are several such palettes defined in palette.go to choose from, as well as more concrete examples in palette_example.go.

pal := gofrac.SpectralPalette{Sweep: 270, Offset: 0}
Maximum iterations

The final parameter to choose is the maximum number of iterations to perform before an unescaped point is considered to converge. Tuning this parameter will increase both the level detail in the resulting image as well as the time needed to produce it.

maxIt := 250
Generate an image

With everything chosen, the only thing left to do is to tell gofrac to create an image for you. The GetImage function does exactly that. Using the objects defined above, one issues the call

img, err := gofrac.GetImage(m, d, &plot, pal, maxIt)

GetImage returns an *image.RGBA, which the standard library's various encoders can use to write an encoded image to disk. Consult the documentation of Go's image package for details.

After doing so, you should have the following image of the Mandelbrot set in your filesystem. Way to go!

Mandelbrot set

Advanced usage

The GetImage function provides a convenient interface to generate images of fractals in a one-off manner but precludes the reuse of results for multiple rendering runs. The FracIt function will return a two-dimensional slice of object containing the output quantities of the iterations. This slice can then be passed to the Render function with different plotters and palettes depending on your needs.

License: 3-Clause BSD

Copyright (c) 2020, Andrew Quinn
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

  • Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Documentation

Overview

Package gofrac implements a fractal generation library

Index

Constants

This section is empty.

Variables

View Source
var BWBands = NewUniformBandedPalette(
	colorful.Hsv(0, 0, 0),
	colorful.Hsv(0, 0, 1),
)

BWBands is a palette of one black and one white color band.

BWBlends is an interpolated version of BWBands.

View Source
var BWStripes = PeriodicPalette{
	Period:        1,
	BandedPalette: BWBands,
}

BWStripes is a periodic version of BWBands for fans of zebras and Tim Burton.

View Source
var PrettyBands = NewUniformBandedPalette(
	colorful.Hsv(24.0, 0.38, 0.33),
	colorful.Hsv(158.0, 0.48, 0.73),
	colorful.Hsv(58.0, 0.72, 0.83),
	colorful.Hsv(58.0, 0.32, 0.95),
	colorful.Hsv(24.0, 0.86, 0.97),
)

PrettyBands is a color palette containing discrete bands of blue, brown, and cream hues.

View Source
var PrettyBands2 = NewUniformBandedPalette(
	colorful.Hsv(27.0, 0.75, 0.25),
	colorful.Hsv(188.0, 0.35, 0.82),
	colorful.Hsv(175.0, 0.13, 0.91),
	colorful.Hsv(35.0, 0.17, 0.85),
	colorful.Hsv(52.0, 0.06, 1.00),
)

PrettyBands2 is similar to PrettyBands, only it contains some additional orange tones.

PrettyBlends is an interpolated version of PrettyBands.

PrettyBlends2 is an interpolated version of PrettyBands2.

View Source
var PrettyPeriodic = PeriodicPalette{
	Period:        1,
	BandedPalette: PrettyBands,
}

PrettyPeriodic is a periodic version of PrettyBands.

View Source
var PrettyPeriodic2 = PeriodicPalette{
	Period:        10,
	BandedPalette: PrettyBands2,
}

PrettyPeriodic2 is a periodic version of PrettyBands2.

View Source
var Spectrum = SpectralPalette{Sweep: 360}

Spectrum is a spectral palette that starts at red and sweeps through the color spectrum.

View Source
var UHDRes = struct {
	w int
	h int
}{/* contains filtered or unexported fields */}

Functions

func GetImage

func GetImage(f Fraccer, d DomainReader, plotter Plotter, palette ColorSampler, maxIterations int) (*image.RGBA, error)

GetImage performs an iterated fractal calculation within a domain and generates an image.RGBA of the output.

f is the fractal generator (i.e., Mandelbrot, Julia, etc.). d is the input domain. plotter maps outputs of f to floating point values. palette maps floating point values to colors. MaxIterations gives the number of iterations to be performed before considering a point to have converged.

func JuliaQExample

func JuliaQExample()

JuliaQExample generates an interesting quadratic Julia set and stores it as "julia.png".

func MandelbrotExample

func MandelbrotExample()

MandelbrotExample generates the classic Mandelbrot image and stores it as "mandelbrot.png".

func NewBitmap

func NewBitmap(r int, c int) bitmap

NewBitmap constructs a slice of length r of slices of color.Colors, each of which are of length c.

func Render

func Render(results *Results, plotter Plotter, palette ColorSampler) bitmap

Render combines the fractal iteration results with a plotting method and generates a bitmap according to the color palette provided.

Types

type BandedPalette

type BandedPalette color.Palette

BandedPalette is an alias for color.Palette, which itself is an alias for a slice of color.Color. It represents a collection of discrete color bands.

func NewUniformBandedPalette

func NewUniformBandedPalette(colors ...color.Color) BandedPalette

NewUniformBandedPalette constructs a BandedPalette containing all of the color.Color items given in colors.

func (BandedPalette) SampleColor

func (p BandedPalette) SampleColor(val float64, maxIterations int) color.Color

type BlendedBandedPalette

type BlendedBandedPalette color.Palette

BlendedBandedPalette is a collection of interpolated color.Color items.

func NewUniformBlendedBandedPalette

func NewUniformBlendedBandedPalette(colors ...color.Color) BlendedBandedPalette

NewUniformBlendedBandedPalette constructs a BlendedBandedPalette containing all of the color.Color items given in colors.

func (BlendedBandedPalette) SampleColor

func (p BlendedBandedPalette) SampleColor(val float64, maxIterations int) color.Color

type CCMap

type CCMap func(complex128) complex128

CCMap is simply a short name for a function f: C -> C

type ColorSampler

type ColorSampler interface {
	// TODO: Make "blackout" color configurable
	// SampleColor returns the color.Color of a palette corresponding to a
	// floating point value given by val.
	SampleColor(val float64, maxIterations int) color.Color
}

ColorSampler converts a floating point value to a color.Color in a color palette.

type Domain

type Domain struct {
	// contains filtered or unexported fields
}

Domain stores bounds and sampling information over a rectangular 2D surface.

The lower-left corner of the domain is stored in (x0, y0) and reaches to the upper-right corner at (x0+xDist, y0+yDist). Along the x and y axes, xs and ys samples are taken, respectively. The inverses of xDist and yDist are stored in wInv and hInv, respectively, to speed up computation.

func NewDomain

func NewDomain(x0, y0, x1, y1 float64, xSamples, ySamples int) (d *Domain, err error)

NewDomain constructs a rectangular 2D domain.

(x0, y0) is the bottom-left corner of the domain. (y0, y1) is the top-right corner of the domain. The domain is sampled xSamples and ySamples times along the x and y axes, respectively.

func (*Domain) At

func (r *Domain) At(i int, j int) (loc complex128, err error)

func (*Domain) Dimensions

func (r *Domain) Dimensions() (rows int, cols int)

type DomainReader

type DomainReader interface {
	// At returns the underlying coordinates of a sample (i, j) in a domain as
	//a complex number, where the sample (0, 0) is the top-left corner of the
	// domain. If a non-existent sample is requested, an error is returned.
	At(i int, j int) (loc complex128, err error)

	// Dimensions returns the number of samples taken along each axis of a
	// domain as rows and columns.
	Dimensions() (rows int, cols int)
}

DomainReader reads values from a discretization of a bounded 2D space.

type EscapeTimePlotter

type EscapeTimePlotter struct {
	PlotterBase
}

EscapeTimePlotter implements the basic plotting method for fractals, which relies solely on the escape time (i.e., pre-bailout iteration count) of an iterated calculation.

func (EscapeTimePlotter) Plot

func (p EscapeTimePlotter) Plot(r *Result) float64

type FracData

type FracData struct {
	// Radius is the bailout radius of a fractal calculation.
	Radius float64

	// MaxIterations is the number of iterations at which an iterated input value is considered convergent if it hasn't
	// exceeded Radius.
	MaxIterations int
	// contains filtered or unexported fields
}

func (*FracData) Data

func (f *FracData) Data() *FracData

func (*FracData) SetDegree

func (f *FracData) SetDegree(d float64)

func (*FracData) SetMaxIterations

func (f *FracData) SetMaxIterations(n int) error

func (*FracData) SetRadius

func (f *FracData) SetRadius(r float64)

type FracDataGetter

type FracDataGetter interface {
	Data() *FracData
}

type Fraccer

type Fraccer interface {
	// Frac performs iterations of a fractal equation for a complex number
	// given by loc.
	Frac(loc complex128) *Result
	SetMaxIterations(iterations int) error
	FracDataGetter
}

Fraccer maps a point in the complex plane to the result of a fractal calculation

type JuliaQ

type JuliaQ struct {
	Quadratic
	C complex128
}

JuliaQ is the quadratic Julia set, which results from iterating the function f_C(z) = z^2 + C for a all complex numbers z and a given complex number C.

func NewJuliaQ

func NewJuliaQ(radius float64, c complex128) *JuliaQ

NewJuliaQ constructs a new JuliaQ struct with a given bailout radius and a complex parameter c corresponding to the C in f_C(z) = z^2 + C.

func (JuliaQ) Frac

func (j JuliaQ) Frac(loc complex128) *Result

type JuliaR

type JuliaR struct {
	FracData
	P func(complex128) complex128
	Q func(complex128) complex128
	C complex128
}

JuliaR is a Julia set generated by a rational complex function given by f_C(z) = P(z) / Q(z) + C.

func (JuliaR) Frac

func (r JuliaR) Frac(loc complex128) *Result

type MandelPG

type MandelPG Polynomiograph

MandelPG is a Mandelbrot-style polynomiograph

func NewMandelPG

func NewMandelPG(eps float64, B CCMap, F CCMap, G CCMap) *MandelPG

NewMandePG returns a new structure with the members required for Mandelbrot-style polynomiograph calculations.

func (MandelPG) Frac

func (m MandelPG) Frac(loc complex128) *Result

type Mandelbrot

type Mandelbrot struct {
	Quadratic
}

The Mandelbrot set, which results from iterating the function f_c(z) = z^2 + c, for all complex numbers c and z_0 = 0.

func NewMandelbrot

func NewMandelbrot(radius float64) *Mandelbrot

NewMandelbrot constructs a Mandelbrot struct with a given bailout radius.

func (Mandelbrot) Frac

func (m Mandelbrot) Frac(loc complex128) *Result

type NormalizedEscapeTimePlotter

type NormalizedEscapeTimePlotter struct {
	PlotterBase
}

NormalizedEscapeTimePlotter is a version of the escape time plotting method in which values are normalized according to the set of diverging results.

func (NormalizedEscapeTimePlotter) Plot

type NormalizedSmoothedEscapeTimePlotter

type NormalizedSmoothedEscapeTimePlotter struct {
	NormalizedEscapeTimePlotter
}

NormalizedSmoothedEscapeTimePlotter performs the electrostatic potential calculation on the normalized escape time results.

func (NormalizedSmoothedEscapeTimePlotter) Plot

type PeriodicPalette

type PeriodicPalette struct {
	BandedPalette
	Period int
}

PeriodicPalette is a cyclic palette of discrete color bands whose width is given by Period.

func (PeriodicPalette) SampleColor

func (p PeriodicPalette) SampleColor(val float64, maxIterations int) color.Color

type PhasePlotter

type PhasePlotter struct {
	PlotterBase
}

PhasePlotter plots an escaped iterate according to its phase when it escapes.

func (PhasePlotter) Plot

func (p PhasePlotter) Plot(r *Result) float64

type Plotter

type Plotter interface {
	// Plot maps a Result object onto a floating point number.
	Plot(r *Result) float64

	// SetFracData sets Plotter's FracData member, which stores information
	// about an iterate, which is necessary for some plotting functions.
	SetFracData(fd *FracData)
}

Plotter can map the output of a fractal calculation to a floating point value in interesting ways.

type PlotterBase

type PlotterBase struct {
	FracData
}

func (*PlotterBase) SetFracData

func (pb *PlotterBase) SetFracData(fd *FracData)

type Polynomiograph

type Polynomiograph struct {
	FracData
	// B is a root-finding rational polynomial of the family used in Newton's,
	// Halley's, or higher-order methods. See the link above for a generalized
	// form.
	B func(z complex128) complex128

	// F maps the input location to an initial value.
	F func(loc complex128) complex128

	// G is the transformation applied to the value c_n after z_{n+1} has been
	// calculated during iterations. That is,
	//    z_{n+1} = B(z_n) + c_n,
	//    c_{n+1} = G(c_n)
	G func(c complex128) complex128
	// contains filtered or unexported fields
}

Polynomiograph contains the data necessary to perform the style of computations described by Kalantari (et al) in several publications. See, for example, https://www.tandfonline.com/doi/full/10.1080/17513472.2019.1600959

type Quadratic

type Quadratic struct {
	FracData
}

Quadratic stores the information needed by a quadratic fractal.

func NewQuadratic

func NewQuadratic(radius float64) Quadratic

type Result

type Result struct {
	Z          complex128
	C          complex128
	Iterations int
	NFactor    float64
}

type Results

type Results struct {
	// contains filtered or unexported fields
}

Results is a 2D slice of Result objects.

func FracIt

func FracIt(d DomainReader, f Fraccer, iterations int) (*Results, error)

FracIt applies the fractal calculation given by f to every sample in the domain d. The maximum number of iterations to be performed is given by iterations.

func NewResults

func NewResults(rows int, cols int, maxIterations int) Results

NewResults constructs a 2D slice of Result objects, with outer and inner dimensions of rows and cols, respectively.

func (Results) At

func (r Results) At(row int, col int) *Result

At retrieves the Result at the coordinates (row, col).

func (Results) Dimensions

func (r Results) Dimensions() (rows int, cols int)

Dimensions returns the outer and inner dimensions of a Results object.

func (Results) Done

func (r Results) Done()

Done finalizes a Results object and triggers calculations that depend on the entirety of a fractal solution.

func (Results) SetResult

func (r Results) SetResult(row int, col int, z complex128, c complex128, iterations int)

SetResult sets the z, c, and iterations fields of the Result located at the coordinates (row, col).

type SmoothedEscapeTimePlotter

type SmoothedEscapeTimePlotter struct {
	PlotterBase
}

SmoothedEscapeTimePlotter maps a Result to a value in a way analogous to calculating the Result's electrostatic potential.

func (SmoothedEscapeTimePlotter) Plot

type SpectralPalette

type SpectralPalette struct {
	Sweep  float64
	Offset float64
}

SpectralPalette contains a range of hues from portion of the HSV color space where S and V are both 1.0. The palette starts at Offset degrees and travels Sweep degrees around the HSV space.

func (SpectralPalette) SampleColor

func (p SpectralPalette) SampleColor(val float64, maxIterations int) color.Color

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL