blob: 0563122ac9cf8c3dfce5b418f0a74d32edf0206f [file] [log] [blame]
// Copyright ©2019 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dot_test
import (
"fmt"
"log"
"math"
"strconv"
"gonum.org/v1/gonum/graph"
"gonum.org/v1/gonum/graph/encoding"
"gonum.org/v1/gonum/graph/encoding/dot"
"gonum.org/v1/gonum/graph/simple"
)
// dotGraph provides a shim for interaction between the DOT
// unmarshaler and a simple.WeightedUndirectedGraph.
type dotGraph struct {
*simple.WeightedUndirectedGraph
}
func newDotGraph() *dotGraph {
return &dotGraph{WeightedUndirectedGraph: simple.NewWeightedUndirectedGraph(0, 0)}
}
// NewEdge returns a DOT-aware edge.
func (g *dotGraph) NewEdge(from, to graph.Node) graph.Edge {
e := g.WeightedUndirectedGraph.NewWeightedEdge(from, to, math.NaN()).(simple.WeightedEdge)
return &weightedEdge{WeightedEdge: e}
}
// NewNode returns a DOT-aware node.
func (g *dotGraph) NewNode() graph.Node {
return &node{Node: g.WeightedUndirectedGraph.NewNode()}
}
// SetEdge is a shim to allow the DOT unmarshaler to
// add weighted edges to a graph.
func (g *dotGraph) SetEdge(e graph.Edge) {
g.WeightedUndirectedGraph.SetWeightedEdge(e.(*weightedEdge))
}
// weightedEdge is a DOT-aware weighted edge.
type weightedEdge struct {
simple.WeightedEdge
}
// SetAttribute sets the weight of the receiver.
func (e *weightedEdge) SetAttribute(attr encoding.Attribute) error {
if attr.Key != "weight" {
return fmt.Errorf("unable to unmarshal node DOT attribute with key %q", attr.Key)
}
var err error
e.W, err = strconv.ParseFloat(attr.Value, 64)
return err
}
// node is a DOT-aware node.
type node struct {
graph.Node
dotID string
}
// SetDOTID sets the DOT ID of the node.
func (n *node) SetDOTID(id string) { n.dotID = id }
func (n *node) String() string { return n.dotID }
const ug = `
graph {
a
b
c
a--b ["weight"=0.5]
a--c ["weight"=1]
}
`
func ExampleUnmarshal_weighted() {
dst := newDotGraph()
err := dot.Unmarshal([]byte(ug), dst)
if err != nil {
log.Fatal(err)
}
for _, e := range graph.EdgesOf(dst.Edges()) {
fmt.Printf("%+v\n", e.(*weightedEdge).WeightedEdge)
}
// Unordered output:
// {F:a T:b W:0.5}
// {F:a T:c W:1}
}