// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.JunctionChecker.junctionchecking;
import java.util.ArrayList;
import java.util.HashSet;
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.Channel;
import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.ChannelDiGraph;
/**
* JunctionChecker startet das Überprüfen eines Subgraphen auf eine existierende
* Kreuzung
*
* @author joerg
*
*/
public class JunctionChecker {
private ArrayList<Channel> subgraph;
private ArrayList<Channel> entries;
private ArrayList<Channel> exits;
private ArrayList<Channel> cycleedges;
private ArrayList<Channel> subjunction;
private int n;
private final JPrepare jPrepare;
private JProcess jProcess;
private final ChannelDiGraph channeldigraph;
private final JCheck jCheck;
private ArrayList<Channel> E;
private int[][] Grid;
private boolean Check;
private boolean smallerJunction;
private JMinimality m;
// Variable wird beim KreuzungsSuchen benutzt, sonst ist sie leer!
private ArrayList<HashSet<Channel>> junctions = new ArrayList<>();
//dient zur Zeitmessung
private long startIterate = 0;
private long stopIterate = 0;
private long startGenerate = 0;
public JunctionChecker(ChannelDiGraph channeldigraph, int n) {
this.jPrepare = new JPrepare(channeldigraph);
this.channeldigraph = channeldigraph;
this.n = n;
this.jCheck = new JCheck();
this.subjunction = new ArrayList<>();
smallerJunction = false;
}
/**
* startet das Überprüfen einer Teilmenge auf die Kreuzungskriterien
*/
public void checkjunctions(ArrayList<Channel> subgraph, ProgressMonitor pm) {
jPrepare.jPrepare(subgraph);
entries = jPrepare.getEntries();
exits = jPrepare.getExits();
jProcess = new JProcess(subgraph, channeldigraph);
jProcess.jProcess(jPrepare.getEntries());
boolean result = jCheck.jCheck(entries, exits, n);
//jPrepare.resetSubgraph();
if (result == true) {
this.collectECandidates(subgraph);
this.ConstructGrid();
m = new JMinimality(Grid, n, E, entries, exits, channeldigraph, pm,
true);
m.GenerateSubcolumns();
Check = m.IterateThroughKn();
if (!Check) {
smallerJunction = true;
}
subjunction = m.getSubJunctionCandidate();
} else {
Check = false;
}
}
/**
* Diese Methode wird aufgerufen, wenn nach Kreuzungen in einer Teilmenge
* gesucht werden soll
*
* @param firstjunction soll nur die erste mögliche Kreuzung ausgegeben werden oder alle
*/
public void junctionSearch(ArrayList<Channel> subgraph, ProgressMonitor pm) {
jPrepare.jPrepare(subgraph);
entries = jPrepare.getEntries();
exits = jPrepare.getExits();
jProcess = new JProcess(subgraph, channeldigraph);
jProcess.jProcess(jPrepare.getEntries());
this.collectECandidates(subgraph);
this.ConstructGrid();
jPrepare.resetSubgraph();
m = new JMinimality(Grid, n, E, new ArrayList<Channel>(), new ArrayList<Channel>(), channeldigraph, pm, false);
m.GenerateSubcolumns();
Check = m.IterateThroughKn();
junctions = checkJunctionCandidates(m.getJunctionCandidates());
}
public void junctionSearch(ArrayList<Channel> subgraph) {
jPrepare.jPrepare(subgraph);
entries = jPrepare.getEntries();
exits = jPrepare.getExits();
jProcess = new JProcess(subgraph, channeldigraph);
jProcess.jProcess(jPrepare.getEntries());
this.collectECandidates(subgraph);
this.ConstructGrid();
jPrepare.resetSubgraph();
m = new JMinimality(Grid, n, E, new ArrayList<Channel>(), new ArrayList<Channel>(), channeldigraph, false);
startGenerate = System.currentTimeMillis();
m.GenerateSubcolumns();
startIterate = System.currentTimeMillis();
Check = m.IterateThroughKn();
stopIterate = System.currentTimeMillis();
junctions = checkJunctionCandidates(m.getJunctionCandidates());
}
/**
* Überprüft die Kreuzunskandidaten, die JMinimality gefunden hat, welche davon eine Kreuzung darstellen (eine Kreuzung
* darf keine weiteren Kreuzungen enthalten)
*/
private ArrayList<HashSet<Channel>> checkJunctionCandidates(ArrayList<HashSet<Channel>> junctioncandidates) {
@SuppressWarnings("unchecked")
ArrayList<HashSet<Channel>> junctions = (ArrayList<HashSet<Channel>>) junctioncandidates.clone();
for (int i = 0; i < junctioncandidates.size(); i++) {
for (int j = 0; j < junctioncandidates.size(); j++) {
if (junctioncandidates.get(i).containsAll(junctioncandidates.get(j))) {
junctions.remove(junctioncandidates.get(i));
}
}
}
return junctions;
}
private void collectECandidates(ArrayList<Channel> subgraph) {
E = new ArrayList<>();
for (int i = 0; i < subgraph.size(); i++) {
if ((subgraph.get(i).getIndegree() + subgraph.get(i).getOutdegree() >= 3)
|| entries.contains(subgraph.get(i))
|| exits.contains(subgraph.get(i))) {
E.add(subgraph.get(i));
}
}
}
private void ConstructGrid() {
Grid = new int[E.size()][E.size()];
for (int y = 0; y < E.size(); y++) {
for (int x = 0; x < E.size(); x++) {
if (x != y && !(entries.contains(E.get(x)))
&& !(exits.contains(E.get(y)))
&& E.get(y).getReachableNodes().contains(E.get(x))) {
Grid[y][x] = 1;
//log.trace("Grid-Position auf 1 gesetzT (y/x): " + y + ":"
// + x + "(Entry/exit):" + E.get(y).getNewid() + ":" +
// E.get(x).getNewid());
} else {
Grid[y][x] = 0;
}
}
}
}
public long getMeasuredIterateTime() {
return (stopIterate - startIterate);
}
public long getMeasuredGenerateTime() {
return (startIterate - startGenerate);
}
public ArrayList<Channel> getSubgraph() {
return subgraph;
}
public void setSubgraph(ArrayList<Channel> subgraph) {
this.subgraph = subgraph;
}
public ArrayList<Channel> getEntries() {
return entries;
}
public void setEntries(ArrayList<Channel> entries) {
this.entries = entries;
}
public ArrayList<Channel> getExits() {
return exits;
}
public void setExits(ArrayList<Channel> exits) {
this.exits = exits;
}
public ArrayList<Channel> getCycleedges() {
return cycleedges;
}
public void setCycleedges(ArrayList<Channel> cycleedges) {
this.cycleedges = cycleedges;
}
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
/**
* gibt die kleinere, gefundene Kreuzung zurück (wenn es sie gibt)
*/
public ArrayList<Channel> getSubJunction() {
return subjunction;
}
/**
* gibt das Ergebnis des JCheck zurück (bei false keine generelle Aussage
* möglich)
*
* @return false = keine Kreuzung ODER enthält kleinere Kreuzung true =
* Kreuzung
*
*/
public boolean getCheck() {
return Check;
}
/**
* gibt den Wert des JMinimality zurück (wenn er ausgeführt wurde)
*
* @return true = keine kleinere kreuzung, false = kleinere kreuzung
* enthalten
*/
public boolean isSmallerJunction() {
return smallerJunction;
}
/**
* das Ergebnis des JCheck als String
*/
public String getJCheckResult() {
return jCheck.getResult();
}
/**
* gitb die bei der Kruezungssuche gefundenen Kreuzungen zurück, sonst
* nichts
*/
public ArrayList<HashSet<Channel>> getJunctions() {
return junctions;
}
}