Documentation
¶
Overview ¶
Package wardleyToGo provides primitives to build an in-memory map (a plan).
In the context of the package "a map" represents a landscape.
The landscape is made of "Components". Each component knows its own location on a map.
Components can collaborate, meaning that they may be linked together. Therefore a map is also a graph.
The entrypoint of this API is the 'Map' structure
Example (Canvas) ¶
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"math"
"strconv"
"github.com/owulveryck/wardleyToGo"
"github.com/owulveryck/wardleyToGo/internal/drawing"
"github.com/owulveryck/wardleyToGo/internal/utils"
"gonum.org/v1/gonum/graph"
"gonum.org/v1/gonum/graph/path"
"gonum.org/v1/gonum/graph/simple"
)
type dummyComponent struct {
id int64
position image.Point
}
func (d *dummyComponent) GetPosition() image.Point { return d.position }
func (d *dummyComponent) String() string { return strconv.FormatInt(d.id, 10) }
func (d *dummyComponent) ID() int64 { return d.id }
func (d *dummyComponent) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
coords := utils.CalcCoords(d.position, r)
dst.Set(coords.X, coords.Y, color.Gray{Y: 255})
}
type dummyCollaboration struct{ simple.Edge }
func (d *dummyCollaboration) GetType() wardleyToGo.EdgeType { return 0 }
func (d *dummyCollaboration) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
coordsF := utils.CalcCoords(d.F.(wardleyToGo.Component).GetPosition(), r)
coordsT := utils.CalcCoords(d.T.(wardleyToGo.Component).GetPosition(), r)
drawing.Line(dst, coordsF.X, coordsF.Y, coordsT.X, coordsT.Y, color.Gray{Y: 128}, [2]int{})
}
func newCollaboration(a, b wardleyToGo.Component) wardleyToGo.Collaboration {
return &dummyCollaboration{Edge: simple.Edge{F: a, T: b}}
}
func main() {
// Create a new map
m := wardleyToGo.NewMap(0)
c0 := &dummyComponent{id: 0, position: image.Pt(25, 25)}
c1 := &dummyComponent{id: 1, position: image.Pt(50, 50)}
c2 := &dummyComponent{id: 2, position: image.Pt(50, 75)}
c3 := &dummyComponent{id: 3, position: image.Pt(75, 75)}
m.AddComponent(c0)
m.AddComponent(c1)
m.AddComponent(c2)
m.AddComponent(c3)
// c0 -> c1
// c1 -> c2
// c2 -> c3
// c1 -> c3
m.SetCollaboration(newCollaboration(c0, c1))
m.SetCollaboration(newCollaboration(c1, c2))
m.SetCollaboration(newCollaboration(c2, c3))
m.SetCollaboration(newCollaboration(c1, c3))
// Creates a picture representation of the map
const width = 80
const height = 40
im := image.NewGray(image.Rectangle{Max: image.Point{X: width, Y: height}})
m.Canvas = &simpleCanvas{}
m.Draw(im, image.Rect(5, 2, 75, 38), im, image.Point{X: 0, Y: 0})
//m.Draw(im, im.Bounds(), im, image.Point{X: 0, Y: 0})
// Very trivial example to draw a map on stdout
render(im)
// drawMap(m)
// Find the shortest path betwen c0 and c3
p, _ := path.AStar(c0, c3, m, euclideanDistance)
c0Toc3, _ := p.To(c3.ID())
fmt.Printf("Shortest path from c0 to c3: ")
for _, c := range c0Toc3 {
fmt.Printf("-%v", c.ID())
}
}
type simpleCanvas struct{}
func (s *simpleCanvas) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
draw.Draw(dst, r, image.NewUniform(color.Gray{Y: 64}), sp, draw.Src)
}
func render(im image.Image) {
width := im.Bounds().Dx()
pi := image.NewPaletted(im.Bounds(), []color.Color{
color.Gray{Y: 255},
color.Gray{Y: 160},
color.Gray{Y: 70},
color.Gray{Y: 35},
color.Gray{Y: 0},
})
draw.FloydSteinberg.Draw(pi, im.Bounds(), im, image.Point{})
shade := []string{" ", "░", "▒", "▓", "█"}
for i, p := range pi.Pix {
fmt.Print(shade[p])
if (i+1)%width == 0 {
fmt.Print("\n")
}
}
}
var euclideanDistance path.Heuristic = func(x, y graph.Node) float64 {
xC := x.(wardleyToGo.Component).GetPosition()
yC := y.(wardleyToGo.Component).GetPosition()
a := xC.X - yC.X
b := xC.Y - yC.Y
return math.Sqrt(float64(a*a) + float64(b*b))
}
Output: ████████████████████████████████████████████████████████████████████████████████ ████████████████████████████████████████████████████████████████████████████████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████ █████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████ █████▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████ █████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████ █████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████ █████▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓ ░▓▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒█████ █████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒░░▓▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▓▒▒▓▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒█████ █████▒▓▒▒▓▒▒▓▒▒▓▒▓▒▒▒▒▒▒▒▒▒▓▒▒░░▓▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▓▒█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▓▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒█████ █████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒░░▓▒▓▒▒▓▒▒▓▒▓▒▓▒▓▒▒▓▒▓▒▓▒▓▒▒▓▒▓▒▓▒▒▒▒▓▒▒▓█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▓▓░░▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒█████ █████▒▓▒▒▓▒▒▓▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▓▒░▒▒▒▓▒▒▓▒▒▒▒▒▓▒▒▒▓▒▒▒▒▓▒▒▒▓▒▒▓▒▒▒▒▓▒▒█████ █████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▓▒▒▓▒▒ ▒▒▒▒▒▒▒▓▒▒▒▒▓▒▒▒▒▓▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒█████ █████▒▒▓▒▒▓▒▒▒▓▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒░▒░▓▒▒▓▒▒▒▓▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒█████ █████▒▒▒▒▒▒▒▓▒▒▒▓▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▓▒▒▒▓▒▒▓░▒▒░▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒█████ █████▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒░░▓▒▒▓▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒█████ █████▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▓▒░▒▒▒▒▓▒░▒▒▒▒▒▓▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▓█████ █████▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒░▓▒▒▒▒▓▒▒░▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒█████ █████▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▓░▓▒▓▒▒▒▒▒▒▒░▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▓▒▒█████ █████▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓░▓▒▒▒▒▓▒▒▓▒▒▒░░▓▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒█████ █████▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▓▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▓▒▒░▓▒▒▒▒▒▒▒▒▒▒▒▓▓░▒▒▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒█████ █████▒▓▒▒▓▒▒▒▒▒▒▒▒▓▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ ░▒░▒░▒░▒░▒░▒░░▒░ ▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒█████ █████▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▓▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒█████ █████▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▓▒█████ █████▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒█████ █████▒▓▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓█████ █████▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒█████ █████▒▒▓▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▓▒▓▒▒▒█████ █████▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▓▒█████ █████▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▓▒▒▓▒▒▒▒█████ ████████████████████████████████████████████████████████████████████████████████ ████████████████████████████████████████████████████████████████████████████████ Shortest path from c0 to c3: -0-1-3
Index ¶
- type Annotation
- type Area
- type Chainer
- type Collaboration
- type Component
- type ComponentType
- type EdgeType
- type Map
- func (m *Map) AddComponent(e Component) error
- func (m *Map) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point)
- func (m *Map) GetArea() image.Rectangle
- func (m *Map) GetPosition() image.Point
- func (m *Map) ID() int64
- func (m *Map) SetCollaboration(e Collaboration) error
- func (m *Map) String() string
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Annotation ¶
An annotation is a set of placements of a certain label
func NewAnnotation ¶
func NewAnnotation(identifier int) *Annotation
func (*Annotation) MarshalSVG ¶ added in v0.3.3
func (*Annotation) String ¶
func (a *Annotation) String() string
type Area ¶
type Area interface {
// GetArea should be expressed wrt a 100x100 map
GetArea() image.Rectangle
graph.Node
}
An area is anything that covers a rectangle area on a map
type Chainer ¶ added in v0.8.1
type Chainer interface {
// GetAbsoluteVisibility returns the visibility of the component as seen from the anchor
GetAbsoluteVisibility() int
}
Chainer is a component that is part of a value chain
type Collaboration ¶
A Collaboration is an edge between two components with a certain type
type Component ¶
type Component interface {
// GetPosition of the element wrt a 100x100 map
GetPosition() image.Point
graph.Node
}
A Component is a node of a graph that have coordinates. A Component can represent iself on a 100x100 map
type Map ¶
type Map struct {
Title string
// Canvas is the function that will draw the initial map
// allowing the placement of the axis, legend and so on
Canvas draw.Drawer
Annotations []*Annotation
AnnotationsPlacement image.Point
*simple.DirectedGraph
// contains filtered or unexported fields
}
a Map is a directed graph whose components knows their own position wrt to an anchor. The anchor is the point A of a rectangle as defined by
A := image.Point{}
image.Rectangle{A, Pt(100, 100)}
func (*Map) AddComponent ¶
AddComponent add e to the graph. It returns an error if e is out-of-bounds, meaning its coordinates are less than 0 or more that 100
func (*Map) Draw ¶
Draw aligns r.Min in dst with sp in src and then replaces the rectangle r in dst with the result of drawing src on dst. If the Components and Collaboration elemts of the maps are draw.Drawer, their methods are called accordingly
func (*Map) GetPosition ¶
GetPosition fulfills the componnts.Component interface. Therefore a map can be a component of another map. This allows doing submaping. The position is the center of the area of the map
func (*Map) ID ¶
a Map fulfills the graph.Node interface; thererfore if can be part of a graph of maps
func (*Map) SetCollaboration ¶
func (m *Map) SetCollaboration(e Collaboration) error
func (*Map) String ¶
Example ¶
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"strconv"
"github.com/owulveryck/wardleyToGo"
"github.com/owulveryck/wardleyToGo/internal/drawing"
"github.com/owulveryck/wardleyToGo/internal/utils"
"gonum.org/v1/gonum/graph/simple"
)
type dummyComponent struct {
id int64
position image.Point
}
func (d *dummyComponent) GetPosition() image.Point { return d.position }
func (d *dummyComponent) String() string { return strconv.FormatInt(d.id, 10) }
func (d *dummyComponent) ID() int64 { return d.id }
func (d *dummyComponent) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
coords := utils.CalcCoords(d.position, r)
dst.Set(coords.X, coords.Y, color.Gray{Y: 255})
}
type dummyCollaboration struct{ simple.Edge }
func (d *dummyCollaboration) GetType() wardleyToGo.EdgeType { return 0 }
func (d *dummyCollaboration) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
coordsF := utils.CalcCoords(d.F.(wardleyToGo.Component).GetPosition(), r)
coordsT := utils.CalcCoords(d.T.(wardleyToGo.Component).GetPosition(), r)
drawing.Line(dst, coordsF.X, coordsF.Y, coordsT.X, coordsT.Y, color.Gray{Y: 128}, [2]int{})
}
func newCollaboration(a, b wardleyToGo.Component) wardleyToGo.Collaboration {
return &dummyCollaboration{Edge: simple.Edge{F: a, T: b}}
}
func main() {
// Create a new map
m := wardleyToGo.NewMap(0)
c0 := &dummyComponent{id: 0, position: image.Pt(25, 25)}
c1 := &dummyComponent{id: 1, position: image.Pt(50, 50)}
c2 := &dummyComponent{id: 2, position: image.Pt(50, 75)}
c3 := &dummyComponent{id: 3, position: image.Pt(75, 75)}
m.AddComponent(c0)
m.AddComponent(c1)
m.AddComponent(c2)
m.AddComponent(c3)
// c0 -> c1
// c1 -> c2
// c2 -> c3
// c1 -> c3
m.SetCollaboration(newCollaboration(c0, c1))
m.SetCollaboration(newCollaboration(c1, c2))
m.SetCollaboration(newCollaboration(c2, c3))
m.SetCollaboration(newCollaboration(c1, c3))
fmt.Println(m)
}
Output:
