grid – github.com/anaseto/grid Index | Examples | Files

package grid

import "github.com/anaseto/grid"

package grid provides a generic two-dimensional matrix slice type.

The package provides utilities for iterating such grids, as well as manipulating positions and ranges.

The API is inspired by the standard Go slice builtin functions and the image standard package.

Index

Examples

Types

type Grid

type Grid[T any] struct {
	// contains filtered or unexported fields
}

Grid represents a two-dimensional matrix of values of any type. It is a slice type, so it represents a rectangular range within an underlying original grid. Due to how it is represented internally, it is more efficient to iterate in row-major order, as in the following pattern:

max := gd.Size()
for y := 0; y < max.Y; y++ {
	for x := 0; x < max.X; x++ {
		p := Point{X: x, Y: y}
		// do something with p and the grid gd
	}
}

Most iterations can be performed using the Slice, Fill, Copy, Map and Iter methods. An alternative choice is to use the Iterator method.

Grid elements must be created with NewGrid.

Example

Code:play 

package main

import (
	"fmt"

	"github.com/anaseto/grid"
)

func main() {
	// Create a new 10x10 grid of runes.
	gd := grid.NewGrid[rune](10, 10)
	// Fill the whole grid with dots.
	gd.Fill('.')
	// Define a range (3,3)-(7,7).
	rg := grid.NewRange(3, 3, 7, 7)
	// Define a slice of the grid using the range.
	rectangle := gd.Slice(rg)
	// Fill the rectangle with #.
	rectangle.Fill('#')
	// Print the grid.
	it := gd.Iterator()
	max := gd.Size()
	for it.Next() {
		fmt.Printf("%c", it.V())
		if it.P().X == max.X-1 {
			fmt.Print("\n")
		}
	}
}

Output:

..........
..........
..........
...####...
...####...
...####...
...####...
..........
..........
..........

func NewGrid

func NewGrid[T any](w, h int) Grid[T]

NewGrid returns a new grid with given width and height in cells. The width and height should be positive or null. The new grid contains all positions (X,Y) with 0 <= X < w and 0 <= Y < h. The grid is filled with the zero value for cells.

func NewGridFromSlice

func NewGridFromSlice[T any](s []T, w int) Grid[T]

NewGridFromSlice builds a grid of width w with initial contents provided by slice s. The slice's length should be a multiple of w. The slice's values are used in row-major order.

func (Grid[T]) At

func (gd Grid[T]) At(p Point) T

At returns the cell at a given position. If the position is out of range, it returns the zero value.

func (Grid[T]) AtU

func (gd Grid[T]) AtU(p Point) T

AtU returns the cell at a given position without checking the grid slice bounds. If the position is out of bounds, it returns a value corresponding to the position in the underlying grid, or the zero value if also out of the underlying grid's range.

It may be somewhat faster than At in tight loops, but most of the time you can get the same performance using GridIterator or iteration functions, which are less error-prone.

func (Grid[T]) Bounds

func (gd Grid[T]) Bounds() Range

Bounds returns the range that is covered by this grid slice within the underlying original grid.

func (Grid[T]) Cap

func (gd Grid[T]) Cap() Point

Cap returns the size (w,h) measuring the grid and the available space past it within the underlying whole grid. In other words, gd.Bounds().Min.Add(Point{x,y}) is the size of the underlying grid.

func (Grid[T]) Contains

func (gd Grid[T]) Contains(p Point) bool

Contains returns true if the given relative position is within the grid.

func (Grid[T]) Contents

func (gd Grid[T]) Contents() []T

Contents returns the grid's current underlying slice with the values of the whole underlying grid, in row-major order.

func (Grid[T]) Copy

func (gd Grid[T]) Copy(src Grid[T]) Point

Copy copies elements from a source grid src into the destination grid gd, and returns the copied grid-slice size, which is the minimum of both grids for each dimension. The result is independent of whether the two grids referenced memory overlaps or not.

func (Grid[T]) Fill

func (gd Grid[T]) Fill(c T)

Fill sets the given cell as content for all the grid positions.

func (Grid[T]) FillFunc

func (gd Grid[T]) FillFunc(fn func(Point) T)

FillFunc updates the content for all the grid positions, in row-major order, using the given function return value.

func (Grid[T]) Iter

func (gd Grid[T]) Iter(fn func(Point, T))

Iter iterates a function on all the grid positions and cells, in row-major order.

func (Grid[T]) Iterator

func (gd Grid[T]) Iterator() GridIterator[T]

Iterator returns an iterator that can be used to iterate on the grid. It may be convenient when more flexibility than the provided by the other iteration functions is needed. It is used as follows:

it := gd.Iterator()
for it.Next() {
	// call it.P() or it.Cell() or it.SetCell() as appropriate
}

func (Grid[T]) Map

func (gd Grid[T]) Map(fn func(Point, T) T)

Map updates the grid content using the given mapping function. The iteration is done in row-major order.

func (Grid[T]) Range

func (gd Grid[T]) Range() Range

Range returns the range with Min set to (0,0) and Max set to gd.Size(). It may be convenient when using Slice with a range Shift.

func (Grid[T]) Resize

func (gd Grid[T]) Resize(w, h int) Grid[T]

Resize is similar to Slice, but it only specifies new dimensions, and if the range goes beyond the underlying original grid range, it will grow the underlying grid. It preserves the content, and any new cells get the zero value.

func (Grid[T]) Set

func (gd Grid[T]) Set(p Point, c T)

Set draws a cell at a given position in the grid. If the position is out of range, the function does nothing.

func (Grid[T]) Size

func (gd Grid[T]) Size() Point

Size returns the grid (width, height) in cells, and is a shorthand for gd.Range().Size().

func (Grid[T]) Slice

func (gd Grid[T]) Slice(rg Range) Grid[T]

Slice returns a rectangular slice of the grid given by a range relative to the grid. If the range is out of bounds of the parent grid, it will be reduced to fit to the available space. The returned grid shares memory with the parent.

type GridIterator

type GridIterator[T any] struct {
	// contains filtered or unexported fields
}

GridIterator represents a stateful iterator for a grid. They are created with the Iterator method.

Example

Code:play 

package main

import (
	"fmt"

	"github.com/anaseto/grid"
)

func main() {
	// Create a new 26x2 grid of runes.
	gd := grid.NewGrid[rune](26, 2)
	// Get an iterator.
	it := gd.Iterator()
	// Iterate on the grid and fill it with successive alphabetic
	// characters.
	r := 'a'
	max := gd.Size()
	for it.Next() {
		it.SetV(r)
		r++
		if it.P().X == max.X-1 {
			r = 'A'
		}
	}
	// Print the grid.
	it.Reset()
	for it.Next() {
		fmt.Printf("%c", it.V())
		if it.P().X == max.X-1 {
			fmt.Print("\n")
		}
	}
}

Output:

abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ

func (*GridIterator[T]) Next

func (it *GridIterator[T]) Next() bool

Next advances the iterator the next position in the grid, using row-major ordering.

func (*GridIterator[T]) P

func (it *GridIterator[T]) P() Point

P returns the iterator's current position.

func (*GridIterator[T]) Reset

func (it *GridIterator[T]) Reset()

Reset resets the iterator's state so that it can be used again.

func (*GridIterator[T]) SetP

func (it *GridIterator[T]) SetP(p Point)

SetP sets the iterator's current position.

func (*GridIterator[T]) SetV

func (it *GridIterator[T]) SetV(c T)

SetV updates cell value at the iterator's current position. It's faster than calling Set on the grid.

func (*GridIterator[T]) V

func (it *GridIterator[T]) V() T

V returns the cell value at the iterator's current position.

type Point

type Point struct {
	X int
	Y int
}

Point represents an (X,Y) position in a grid.

It follows conventions similar to the ones used by the standard library image.Point.

func (Point) Add

func (p Point) Add(q Point) Point

Add returns vector p+q.

func (Point) Div

func (p Point) Div(k int) Point

Div returns the vector p/k.

func (Point) In

func (p Point) In(rg Range) bool

In reports whether the position is within the given range.

func (Point) Mul

func (p Point) Mul(k int) Point

Mul returns the vector p*k.

func (Point) Shift

func (p Point) Shift(x, y int) Point

Shift returns a new point with coordinates shifted by (x,y). It's a shorthand for p.Add(Point{x,y}).

func (Point) String

func (p Point) String() string

String returns a string representation of the form "(x,y)".

func (Point) Sub

func (p Point) Sub(q Point) Point

Sub returns vector p-q.

type Range

type Range struct {
	Min, Max Point
}

Range represents a rectangle in a grid that contains all the positions P such that Min <= P < Max coordinate-wise. A range is well-formed if Min <= Max. When non-empty, Min represents the upper-left position in the range, and Max-(1,1) the lower-right one.

It follows conventions similar to the ones used by the standard library image.Rectangle.

func NewRange

func NewRange(x0, y0, x1, y1 int) Range

NewRange returns a new Range with coordinates (x0, y0) for Min and (x1, y1) for Max. The returned range will have minimum and maximum coordinates swapped if necessary, so that the range is well-formed.

func (Range) Add

func (rg Range) Add(p Point) Range

Add returns a range of same size translated by +p.

func (Range) Column

func (rg Range) Column(x int) Range

Column reduces the range to relative column x, or an empty range if out of bounds.

func (Range) Columns

func (rg Range) Columns(x0, x1 int) Range

Columns reduces the range to relative columns between x0 (included) and x1 (excluded), or an empty range if out of bounds.

func (Range) Empty

func (rg Range) Empty() bool

Empty reports whether the range contains no positions.

func (Range) Eq

func (rg Range) Eq(r Range) bool

Eq reports whether the two ranges contain the same set of points. All empty ranges are considered equal.

func (Range) In

func (rg Range) In(r Range) bool

In reports whether range rg is completely contained in range r.

func (Range) Intersect

func (rg Range) Intersect(r Range) Range

Intersect returns the largest range contained both by rg and r. If the two ranges do not overlap, the zero range will be returned.

func (Range) Iter

func (rg Range) Iter(fn func(Point))

Iter calls a given function for all the positions of the range.

func (Range) Line

func (rg Range) Line(y int) Range

Line reduces the range to relative line y, or an empty range if out of bounds.

func (Range) Lines

func (rg Range) Lines(y0, y1 int) Range

Lines reduces the range to relative lines between y0 (included) and y1 (excluded), or an empty range if out of bounds.

func (Range) Overlaps

func (rg Range) Overlaps(r Range) bool

Overlaps reports whether the two ranges have a non-zero intersection.

func (Range) Shift

func (rg Range) Shift(x0, y0, x1, y1 int) Range

Shift returns a new range with coordinates shifted by (x0,y0) and (x1,y1).

func (Range) Size

func (rg Range) Size() Point

Size returns the (width, height) of the range in cells.

func (Range) String

func (rg Range) String() string

String returns a string representation of the form "(x0,y0)-(x1,y1)".

func (Range) Sub

func (rg Range) Sub(p Point) Range

Sub returns a range of same size translated by -p.

func (Range) Union

func (rg Range) Union(r Range) Range

Union returns the smallest range containing both rg and r.

Source Files

grid.go

Version
v0.2.0 (latest)
Published
Dec 22, 2021
Platform
linux/amd64
Imports
1 packages
Last checked
8 months ago

Tools for package owners.