// Copyright (c) 2010, 2020 Kiel University and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0.
//
// SPDX-License-Identifier: EPL-2.0

// Package p2layers implements ELK Layered phase 2.
package p2layers import ( basegraph ) const iterationLimitFactor = 4 type NetworkSimplexLayerer struct{} func (*NetworkSimplexLayerer) ( *layered.LGraphArena, layered.LGraphID, ) layered.ProcessorConfiguration { return layered.NetworkSimplexLayeringConfiguration() } func (*NetworkSimplexLayerer) ( *layered.LGraphArena, layered.LGraphID) error { := .Graph() := .LayerlessNodes if len() == 0 { return nil } := connectedComponents(, ) := basegraph.Get(&.Properties, layered.Thoroughness) * iterationLimitFactor var []int for , := range { := make(map[layered.LNodeID]struct{}, len()) for , := range { [] = struct{}{} } := func( layered.LNodeID) []layered.LEdgeID { := make([]layered.LEdgeID, 0) for , := range .NodeOutgoingEdges() { if .EdgeIsSelfLoop() { continue } if , := [.EdgeTargetNode()]; { = append(, ) } } return } := * int(math.Sqrt(float64(len()))) := networksimplex.Layer(networksimplex.Adapter[layered.LNodeID, layered.LEdgeID]{ Nodes: , Outgoing: , Source: .EdgeSourceNode, Target: .EdgeTargetNode, Weight: func( layered.LEdgeID) float64 { := basegraph.Get(&.Edge().Properties, layered.PriorityShortness) if < 1 { = 1 } return float64() }, MinLength: func(layered.LEdgeID) int { return 1 }, }, networksimplex.Options{ Balance: true, PreviousLayeringNodeCounts: , IterationLimit: , }) for , := range { := [] for len(.Layers) <= { .AddLayerToGraph() } := .Layers[] .SetNodeLayer(, &) } if len() > 1 { = make([]int, len(.Layers)) for , := range .Layers { [] = len(.Layer().Nodes) } } } .LayerlessNodes = .LayerlessNodes[:0] return nil } func connectedComponents( *layered.LGraphArena, []layered.LNodeID) [][]layered.LNodeID { for , := range { .Node().ID = } := make([]bool, len()) := make([][]layered.LNodeID, 0) var func(layered.LNodeID, *[]layered.LNodeID) = func( layered.LNodeID, *[]layered.LNodeID) { := .Node().ID if [] { return } [] = true * = append(*, ) for , := range .Node().Ports { for , := range .PortConnectedEdges() { := .EdgeOtherNode(, ) if ![.Node().ID] { (, ) } } } } for , := range { if [.Node().ID] { continue } := make([]layered.LNodeID, 0) (, &) if len() == 0 || len([0]) < len() { = append(, nil) copy([1:], [:len()-1]) [0] = } else { = append(, ) } } return }