mirror of
https://github.com/gonum/gonum.git
synced 2025-10-06 23:52:47 +08:00
encoding/dot: fix ports on undirected graphs
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -29,6 +29,7 @@ Iakov Davydov <iakov.davydov@unil.ch>
|
||||
Jalem Raj Rohit <jrajrohit33@gmail.com>
|
||||
James Bell <james@stellentus.com>
|
||||
James Bowman <james.edward.bowman@gmail.com>
|
||||
James Holmes <32bitkid@gmail.com>
|
||||
Janne Snabb <snabb@epipe.com>
|
||||
Jeff Juozapaitis <jjjuozap@email.arizona.edu>
|
||||
Jeremy Atkinson <jchatkinson@gmail.com>
|
||||
|
@@ -36,6 +36,7 @@ Iakov Davydov <iakov.davydov@unil.ch>
|
||||
Jalem Raj Rohit <jrajrohit33@gmail.com>
|
||||
James Bell <james@stellentus.com>
|
||||
James Bowman <james.edward.bowman@gmail.com>
|
||||
James Holmes <32bitkid@gmail.com>
|
||||
Janne Snabb <snabb@epipe.com>
|
||||
Jeff Juozapaitis <jjjuozap@email.arizona.edu>
|
||||
Jeremy Atkinson <jchatkinson@gmail.com>
|
||||
|
@@ -41,7 +41,12 @@ type Attributers interface {
|
||||
// to the the DOT node port to be used by the edge, compass corresponds
|
||||
// to DOT compass point to which the edge will be aimed.
|
||||
type Porter interface {
|
||||
// FromPort returns the port and compass for the
|
||||
// From node of a graph.Edge.
|
||||
FromPort() (port, compass string)
|
||||
|
||||
// ToPort returns the port and compass for the
|
||||
// To node of a graph.Edge.
|
||||
ToPort() (port, compass string)
|
||||
}
|
||||
|
||||
@@ -219,9 +224,14 @@ func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool
|
||||
} else {
|
||||
p.writeNode(n)
|
||||
}
|
||||
e, edgeIsPorter := g.Edge(nid, tid).(Porter)
|
||||
e := g.Edge(nid, tid)
|
||||
porter, edgeIsPorter := e.(Porter)
|
||||
if edgeIsPorter {
|
||||
p.writePorts(e.FromPort())
|
||||
if e.From().ID() == nid {
|
||||
p.writePorts(porter.FromPort())
|
||||
} else {
|
||||
p.writePorts(porter.ToPort())
|
||||
}
|
||||
}
|
||||
|
||||
if isDirected {
|
||||
@@ -241,7 +251,11 @@ func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool
|
||||
p.writeNode(t)
|
||||
}
|
||||
if edgeIsPorter {
|
||||
p.writePorts(e.ToPort())
|
||||
if e.From().ID() == nid {
|
||||
p.writePorts(porter.ToPort())
|
||||
} else {
|
||||
p.writePorts(porter.FromPort())
|
||||
}
|
||||
}
|
||||
|
||||
if a, ok := g.Edge(nid, tid).(encoding.Attributer); ok {
|
||||
|
@@ -256,14 +256,6 @@ func (e portedEdge) From() graph.Node { return e.from }
|
||||
func (e portedEdge) To() graph.Node { return e.to }
|
||||
func (e portedEdge) Weight() float64 { return 0 }
|
||||
|
||||
// TODO(kortschak): Figure out a better way to handle the fact that
|
||||
// headedness is an undefined concept in undirected graphs. We sort
|
||||
// nodes by ID, so lower ID nodes are always from nodes in undirected
|
||||
// graphs. We can probably do this in the printer, but I am leaving
|
||||
// this here as a WARNING.
|
||||
// Maybe the approach should be to document that for undirected graphs
|
||||
// the low ID node should be returned by the FromPort and the high ID
|
||||
// by the ToPort calls.
|
||||
func (e portedEdge) FromPort() (port, compass string) {
|
||||
return e.fromPort, e.fromCompass
|
||||
}
|
||||
@@ -1054,14 +1046,7 @@ var encodeTests = []struct {
|
||||
{from: 2, to: 3}: {fromPort: "Zwei", fromCompass: "e"},
|
||||
{from: 2, to: 4}: {fromPort: "Two", fromCompass: "w", toPort: "Four", toCompass: "w"},
|
||||
{from: 3, to: 4}: {toPort: "Four", toCompass: "w"},
|
||||
|
||||
// This definition is reversed (see comment above at portedEdge
|
||||
// definition) so that 4 gets the from port. This is a result
|
||||
// of the fact that we sort nodes by ID, so the lower node
|
||||
// will be always be printed first when the graph is undirected,
|
||||
// thus becoming the from port, but we define the edges here
|
||||
// from a directed adjacency list.
|
||||
{from: 4, to: 0}: {fromCompass: "s", toPort: "Four", toCompass: "_"},
|
||||
{from: 4, to: 0}: {fromPort: "Four", fromCompass: "_", toCompass: "s"},
|
||||
},
|
||||
),
|
||||
|
||||
|
47
graph/encoding/dot/example_test.go
Normal file
47
graph/encoding/dot/example_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright ©2018 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"
|
||||
|
||||
"gonum.org/v1/gonum/graph/encoding/dot"
|
||||
"gonum.org/v1/gonum/graph/simple"
|
||||
)
|
||||
|
||||
type edgeWithPorts struct {
|
||||
simple.Edge
|
||||
fromPort, toPort string
|
||||
}
|
||||
|
||||
func (e *edgeWithPorts) FromPort() (string, string) {
|
||||
return e.fromPort, ""
|
||||
}
|
||||
|
||||
func (e *edgeWithPorts) ToPort() (string, string) {
|
||||
return e.toPort, ""
|
||||
}
|
||||
|
||||
func ExamplePorter() {
|
||||
g := simple.NewUndirectedGraph()
|
||||
g.SetEdge(&edgeWithPorts{
|
||||
Edge: simple.Edge{simple.Node(1), simple.Node(0)},
|
||||
fromPort: "p1",
|
||||
toPort: "p2",
|
||||
})
|
||||
|
||||
result, _ := dot.Marshal(g, "", "", " ", true)
|
||||
fmt.Print(string(result))
|
||||
|
||||
// Output:
|
||||
// strict graph {
|
||||
// // Node definitions.
|
||||
// 0;
|
||||
// 1;
|
||||
//
|
||||
// // Edge definitions.
|
||||
// 0:p2 -- 1:p1;
|
||||
// }
|
||||
}
|
Reference in New Issue
Block a user