// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.JunctionChecker.connectedness; import java.util.ArrayList; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.Channel; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.ChannelDiGraph; public class StrongConnectednessCalculator { private int index = 0; private final ArrayList<Channel> stack = new ArrayList<>(); private final ArrayList<ArrayList<Channel>> SCC = new ArrayList<>(); private final int numberOfNodes; private int calculatedNodes = 0; private ArrayList<Channel> nsccchannels = new ArrayList<>(); private final ChannelDiGraph digraph; int biggestPart = 0; public StrongConnectednessCalculator(ChannelDiGraph digraph) { this.digraph = digraph; numberOfNodes = digraph.numberOfChannels(); } private int findUncalculatedNodes() { for (int i = 0; i < numberOfNodes; i++) { if (digraph.getChannelAtPosition(i).getLowlink() == -1) { return i; } } return 0; } /** * berechnet die starken Zusammenhangskomponenten */ public void calculateSCC() { while (calculatedNodes != numberOfNodes) { //log.trace("calculatedNodes: " + calculatedNodes + ", gesamtnodes: " + numberOfNodes); tarjan(digraph.getChannelAtPosition(findUncalculatedNodes())); } //log.trace("Berechnung der starken Zusammenhangskomponenten beendet: \n " +numberOfNodes + " Nodes sind wie folgt aufgeteilt: "); for (int i = 0; i < SCC.size(); i++) { //log.trace("Komponente: " + i + " besteht aus " + SCC.get(i).size()+ " Knoten"); /** * for (int j = 1; j < list.getNumberOfNodes(); j++) { if * (list.getAdjacencyListnodes()[j].getIndex()== -1) { * System.out.println("===="); * System.out.println(list.getAdjacencyListnodes * ()[j].getNode().toString()); } } **/ } findBiggestPiece(); saveNotSCCChannel(); } /** * speichert alle Channel, die nicht stark zusammenhängend sind, in einer ArrayList **/ private void saveNotSCCChannel() { nsccchannels = new ArrayList<>(); for (int i = 0; i < SCC.size(); i++) { if (i != biggestPart) { nsccchannels.addAll(SCC.get(i)); } } //alle Channels auf nicht zusammenhängend setzen for (int i = 0; i < nsccchannels.size(); i++) { nsccchannels.get(i).setStrongConnected(false); } } private void findBiggestPiece() { int number = 0; for (int i = 0; i < SCC.size(); i++) { if (SCC.get(i).size() > number) { biggestPart = i; number = SCC.get(i).size(); } } } public String showNotstronglyConnectednessParts() { String s = new String(); for (int i = 0; i < SCC.size(); i++) { if (i != biggestPart) { s += "GraphKomponente: " + i + "\n"; for (int j = 0; j < SCC.get(i).size(); j++) { s += "Channel: " + SCC.get(i).get(j).getNewid(); } s += "\n"; } } return s; } /** * gibt eine Arraylist mit all den Channels zurück, welche nicht * im größten zusammenhägendem Teil des Channel-Digraphen sind */ public ArrayList<Channel> getNotConnectedChannels() { return nsccchannels; } private void tarjan(Channel v) { //log.trace("tarjan für channel aufgerufen mit id: " + v.getNewid()); v.setIndex(index); v.setLowlink(index); index++; stack.add(0, v); //log.trace("channel "+v.getNewid() + " hat nachbarn: " + v.getLeadsTo().size()); for (int i = 0; i < v.getLeadsTo().size(); i++) { //log.trace("schleifendurchlauf: " + i); Channel n = v.getLeadsTo().get(i).getToChannel(); if (n.getIndex() == -1) { //log.trace("n hat index =-1"); tarjan(n); v.setLowlink(Math.min(v.getLowlink(), n.getLowlink())); } else if (stack.contains(n)) { //log.trace("setze lowlink von n auf: " + v.getLowlink()); v.setLowlink(Math.min(v.getLowlink(), n.getLowlink())); } } if (v.getLowlink() == v.getIndex()) { Channel n; ArrayList<Channel> component = new ArrayList<>(); do { n = stack.remove(0); component.add(n); } while (n != v); SCC.add(component); calculatedNodes += component.size(); } } }