package p3order
import "github.com/d2lang/elk-go/internal/layered"
type AllCrossingsCounter struct {
crossingCounter *CrossingsCounter
hasHyperEdgesEastOfIndex []bool
hasNorthSouthPorts []bool
inLayerEdgeCounts []int
nPorts int
}
func NewAllCrossingsCounter (numberOfLayers int ) *AllCrossingsCounter {
return &AllCrossingsCounter {
hasHyperEdgesEastOfIndex : make ([]bool , numberOfLayers ),
hasNorthSouthPorts : make ([]bool , numberOfLayers ),
inLayerEdgeCounts : make ([]int , numberOfLayers ),
}
}
func (counter *AllCrossingsCounter ) CountAllCrossings (
arena *layered .LGraphArena ,
currentOrder [][]layered .LNodeID ,
) int {
if len (currentOrder ) == 0 {
return 0
}
if counter .crossingCounter == nil {
panic ("p3order: AllCrossingsCounter used before InitAfterTraversal" )
}
crossings := counter .crossingCounter .CountInLayerCrossingsOnSide (arena , currentOrder [0 ], layered .WestSide )
crossings += counter .crossingCounter .CountInLayerCrossingsOnSide (arena , currentOrder [len (currentOrder )-1 ], layered .EastSide )
for layerIndex := range currentOrder {
crossings += counter .countCrossingsAt (arena , layerIndex , currentOrder )
}
return crossings
}
func (counter *AllCrossingsCounter ) countCrossingsAt (
arena *layered .LGraphArena ,
layerIndex int ,
currentOrder [][]layered .LNodeID ,
) int {
total := 0
leftLayer := currentOrder [layerIndex ]
if layerIndex < len (currentOrder )-1 {
rightLayer := currentOrder [layerIndex +1 ]
if counter .hasHyperEdgesEastOfIndex [layerIndex ] {
total = countHyperedgeCrossings (arena , counter .crossingCounter .PortPositions , leftLayer , rightLayer )
total += counter .crossingCounter .CountInLayerCrossingsOnSide (arena , leftLayer , layered .EastSide )
total += counter .crossingCounter .CountInLayerCrossingsOnSide (arena , rightLayer , layered .WestSide )
} else {
total = counter .crossingCounter .CountCrossingsBetweenLayers (arena , leftLayer , rightLayer )
}
}
if counter .hasNorthSouthPorts [layerIndex ] {
total += counter .crossingCounter .CountNorthSouthPortCrossingsInLayer (arena , leftLayer )
}
return total
}
func (counter *AllCrossingsCounter ) InitAtNodeLevel (
arena *layered .LGraphArena ,
layerIndex , nodeIndex int ,
nodeOrder [][]layered .LNodeID ,
) {
nodeID := nodeOrder [layerIndex ][nodeIndex ]
counter .hasNorthSouthPorts [layerIndex ] = counter .hasNorthSouthPorts [layerIndex ] ||
arena .Node (nodeID ).Type == layered .NorthSouthPortNode
}
func (counter *AllCrossingsCounter ) InitAtPortLevel (
arena *layered .LGraphArena ,
layerIndex , nodeIndex , portIndex int ,
nodeOrder [][]layered .LNodeID ,
) {
portID := arena .Node (nodeOrder [layerIndex ][nodeIndex ]).Ports [portIndex ]
arena .Port (portID ).ID = counter .nPorts
counter .nPorts ++
port := arena .Port (portID )
if len (port .OutgoingEdges )+len (port .IncomingEdges ) > 1 {
if port .Side == layered .EastSide {
counter .hasHyperEdgesEastOfIndex [layerIndex ] = true
} else if port .Side == layered .WestSide && layerIndex > 0 {
counter .hasHyperEdgesEastOfIndex [layerIndex -1 ] = true
}
}
}
func (counter *AllCrossingsCounter ) InitAtEdgeLevel (
arena *layered .LGraphArena ,
layerIndex , nodeIndex , portIndex int ,
edgeID layered .LEdgeID ,
nodeOrder [][]layered .LNodeID ,
) {
portID := arena .Node (nodeOrder [layerIndex ][nodeIndex ]).Ports [portIndex ]
edge := arena .Edge (edgeID )
if edge .Source != nil && *edge .Source == portID && arena .EdgeIsInLayer (edgeID ) {
counter .inLayerEdgeCounts [layerIndex ]++
}
}
func (counter *AllCrossingsCounter ) InitAfterTraversal () {
counter .crossingCounter = NewCrossingsCounter (make ([]int , counter .nPorts ))
}
func InitializeAllCrossingsCounter (
counter *AllCrossingsCounter ,
arena *layered .LGraphArena ,
nodeOrder [][]layered .LNodeID ,
) {
for layerIndex , nodes := range nodeOrder {
for nodeIndex , nodeID := range nodes {
counter .InitAtNodeLevel (arena , layerIndex , nodeIndex , nodeOrder )
for portIndex , portID := range arena .Node (nodeID ).Ports {
counter .InitAtPortLevel (arena , layerIndex , nodeIndex , portIndex , nodeOrder )
for _ , edgeID := range arena .PortConnectedEdges (portID ) {
counter .InitAtEdgeLevel (arena , layerIndex , nodeIndex , portIndex , edgeID , nodeOrder )
}
}
}
}
counter .InitAfterTraversal ()
}
The pages are generated with Golds v0.8.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .