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>
|
Jalem Raj Rohit <jrajrohit33@gmail.com>
|
||||||
James Bell <james@stellentus.com>
|
James Bell <james@stellentus.com>
|
||||||
James Bowman <james.edward.bowman@gmail.com>
|
James Bowman <james.edward.bowman@gmail.com>
|
||||||
|
James Holmes <32bitkid@gmail.com>
|
||||||
Janne Snabb <snabb@epipe.com>
|
Janne Snabb <snabb@epipe.com>
|
||||||
Jeff Juozapaitis <jjjuozap@email.arizona.edu>
|
Jeff Juozapaitis <jjjuozap@email.arizona.edu>
|
||||||
Jeremy Atkinson <jchatkinson@gmail.com>
|
Jeremy Atkinson <jchatkinson@gmail.com>
|
||||||
|
@@ -36,6 +36,7 @@ Iakov Davydov <iakov.davydov@unil.ch>
|
|||||||
Jalem Raj Rohit <jrajrohit33@gmail.com>
|
Jalem Raj Rohit <jrajrohit33@gmail.com>
|
||||||
James Bell <james@stellentus.com>
|
James Bell <james@stellentus.com>
|
||||||
James Bowman <james.edward.bowman@gmail.com>
|
James Bowman <james.edward.bowman@gmail.com>
|
||||||
|
James Holmes <32bitkid@gmail.com>
|
||||||
Janne Snabb <snabb@epipe.com>
|
Janne Snabb <snabb@epipe.com>
|
||||||
Jeff Juozapaitis <jjjuozap@email.arizona.edu>
|
Jeff Juozapaitis <jjjuozap@email.arizona.edu>
|
||||||
Jeremy Atkinson <jchatkinson@gmail.com>
|
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 the the DOT node port to be used by the edge, compass corresponds
|
||||||
// to DOT compass point to which the edge will be aimed.
|
// to DOT compass point to which the edge will be aimed.
|
||||||
type Porter interface {
|
type Porter interface {
|
||||||
|
// FromPort returns the port and compass for the
|
||||||
|
// From node of a graph.Edge.
|
||||||
FromPort() (port, compass string)
|
FromPort() (port, compass string)
|
||||||
|
|
||||||
|
// ToPort returns the port and compass for the
|
||||||
|
// To node of a graph.Edge.
|
||||||
ToPort() (port, compass string)
|
ToPort() (port, compass string)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,9 +224,14 @@ func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool
|
|||||||
} else {
|
} else {
|
||||||
p.writeNode(n)
|
p.writeNode(n)
|
||||||
}
|
}
|
||||||
e, edgeIsPorter := g.Edge(nid, tid).(Porter)
|
e := g.Edge(nid, tid)
|
||||||
|
porter, edgeIsPorter := e.(Porter)
|
||||||
if edgeIsPorter {
|
if edgeIsPorter {
|
||||||
p.writePorts(e.FromPort())
|
if e.From().ID() == nid {
|
||||||
|
p.writePorts(porter.FromPort())
|
||||||
|
} else {
|
||||||
|
p.writePorts(porter.ToPort())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isDirected {
|
if isDirected {
|
||||||
@@ -241,7 +251,11 @@ func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool
|
|||||||
p.writeNode(t)
|
p.writeNode(t)
|
||||||
}
|
}
|
||||||
if edgeIsPorter {
|
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 {
|
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) To() graph.Node { return e.to }
|
||||||
func (e portedEdge) Weight() float64 { return 0 }
|
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) {
|
func (e portedEdge) FromPort() (port, compass string) {
|
||||||
return e.fromPort, e.fromCompass
|
return e.fromPort, e.fromCompass
|
||||||
}
|
}
|
||||||
@@ -1054,14 +1046,7 @@ var encodeTests = []struct {
|
|||||||
{from: 2, to: 3}: {fromPort: "Zwei", fromCompass: "e"},
|
{from: 2, to: 3}: {fromPort: "Zwei", fromCompass: "e"},
|
||||||
{from: 2, to: 4}: {fromPort: "Two", fromCompass: "w", toPort: "Four", toCompass: "w"},
|
{from: 2, to: 4}: {fromPort: "Two", fromCompass: "w", toPort: "Four", toCompass: "w"},
|
||||||
{from: 3, to: 4}: {toPort: "Four", toCompass: "w"},
|
{from: 3, to: 4}: {toPort: "Four", toCompass: "w"},
|
||||||
|
{from: 4, to: 0}: {fromPort: "Four", fromCompass: "_", toCompass: "s"},
|
||||||
// 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: "_"},
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
|
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