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 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 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: