All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mdr.ascii.layout.LayeringCalculator.scala Maven / Gradle / Ivy

package com.github.mdr.ascii.layout

import scala.collection.mutable.ListBuffer

class LayeringCalculator[V] {

  private def calculateLongestDistances(graph: Graph[V]): Map[V, Int] = {

    var longestDistancesToSink: Map[V, Int] = Map()

    def isSink(v: V) = graph.outVertices(v).isEmpty
    val sinks = graph.vertices.filter(isSink)
    for (sink ← sinks)
      longestDistancesToSink += sink -> 0

    var finalisedVertices: Set[V] = sinks.toSet
    var boundary = finalisedVertices

    while (boundary.nonEmpty) {
      var newBoundary: Set[V] = Set()
      for {
        v2 ← boundary
        v1 ← graph.inVertices(v2)
        currentKnownLongestToSink = longestDistancesToSink.getOrElse(v1, 0)
      } {
        longestDistancesToSink += v1 -> math.max(currentKnownLongestToSink, longestDistancesToSink(v2) + 1)
        if (graph.outVertices(v1).forall(finalisedVertices)) {
          finalisedVertices += v1
          newBoundary += v1
        }
      }
      boundary = newBoundary
    }
    longestDistancesToSink
  }

  def assignLayers(graph: Graph[V], reversedEdges: Set[(V, V)]): Layering = {
    val longestDistancesToSink = calculateLongestDistances(graph)
    val maxLayerNum = longestDistancesToSink.values.max
    def layerNum(v: V): Int = maxLayerNum - longestDistancesToSink(v)

    val realVertices: Map[V, RealVertex] = graph.vertices.map { v ⇒ v -> new RealVertex(v) }.toMap

    val layers: ListBuffer[ListBuffer[Vertex]] = ListBuffer()
    for (layerNum ← 0 to maxLayerNum)
      layers += ListBuffer[Vertex]()

    for (v ← graph.vertices)
      layers(layerNum(v)) += realVertices(v)

    var edges: List[Edge] = Nil
    for {
      (from, to) ← graph.edges
      fromLayer = layerNum(from)
      toLayer = layerNum(to)
    } {
      val dummies = (fromLayer + 1) to (toLayer - 1) map { layerNum ⇒
        val dummy = new DummyVertex()
        layers(layerNum) += dummy
        dummy
      }
      val vertexChain = realVertices(from) +: dummies :+ realVertices(to)
      for ((v1, v2) ← vertexChain.zip(vertexChain.tail))
        edges ::= new Edge(v1, v2, reversed = reversedEdges.contains((from, to)))
    }

    Layering(layers.toList.map(lb ⇒ Layer(lb.toList)), edges)
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy