/*
* This file is part of the Trickl Open Source Libraries.
*
* Trickl Open Source Libraries - http://open.trickl.com/
*
* Copyright (C) 2011 Tim Gee.
*
* Trickl Open Source Libraries are free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Trickl Open Source Libraries are distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this project. If not, see <http://www.gnu.org/licenses/>.
*/
package com.trickl.graph.planar;
import com.trickl.graph.SpanningSearchVisitor;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Map;
import org.jgrapht.Graph;
class PlanarDfsVisitor<V, E> implements SpanningSearchVisitor<V, E> {
private static class PlanarDfsDetail<V, E> {
int lowPoint;
V parent;
int dfsNumber;
int leastAncestor;
E dfsEdge;
}
private Map<V, PlanarDfsDetail<V, E>> vertexDetails;
private int count = 0;
private Graph<V, E> graph;
public PlanarDfsVisitor(Graph<V, E> graph) {
this.graph = graph;
vertexDetails = new Hashtable<V, PlanarDfsDetail<V, E>>();
}
@Override
public void startVertex(V u) {
PlanarDfsDetail<V, E> detail = vertexDetails.get(u);
if (detail == null) {
detail = new PlanarDfsDetail<V, E>();
vertexDetails.put(u, detail);
}
detail.parent = u;
detail.leastAncestor = count;
}
@Override
public void discoverVertex(V u) {
PlanarDfsDetail<V, E> detail = vertexDetails.get(u);
if (detail == null) {
detail = new PlanarDfsDetail<V, E>();
vertexDetails.put(u, detail);
}
detail.lowPoint = count;
detail.dfsNumber = count;
setCount(getCount() + 1);
}
@Override
public void treeEdge(V source, V target) {
E edge = graph.getEdge(source, target);
PlanarDfsDetail<V, E> targetDetail = vertexDetails.get(target);
PlanarDfsDetail<V, E> sourceDetail = vertexDetails.get(source);
targetDetail.parent = source;
targetDetail.dfsEdge = edge;
targetDetail.leastAncestor = sourceDetail.dfsNumber;
}
@Override
public void backEdge(V source, V target) {
E edge = graph.getEdge(source, target);
PlanarDfsDetail<V, E> sourceDetail = vertexDetails.get(source);
PlanarDfsDetail<V, E> targetDetail = vertexDetails.get(target);
if (!target.equals(sourceDetail.parent)) {
int sourceLowPoint = sourceDetail.lowPoint;
int targetDfsNumber = targetDetail.dfsNumber;
int sourceLeastAncestor = sourceDetail.leastAncestor;
sourceDetail.lowPoint = Math.min(sourceLowPoint, targetDfsNumber);
sourceDetail.leastAncestor = Math.min(sourceLeastAncestor, targetDfsNumber);
}
}
@Override
public void finishVertex(V u) {
PlanarDfsDetail<V, E> detail = vertexDetails.get(u);
V parent = detail.parent;
PlanarDfsDetail<V, E> parentDetail = vertexDetails.get(parent);
int parentlowPoint = parentDetail.lowPoint;
int lowPoint = detail.lowPoint;
if (!parent.equals(u)) {
parentDetail.lowPoint = Math.min(lowPoint, parentlowPoint);
}
}
@Override
public void initializeVertex(V u) {
}
@Override
public void examineEdge(V source, V target) {
}
@Override
public void forwardOrCrossEdge(V source, V target) {
}
public static class LowPointComparator<V, E> implements Comparator<V> {
protected Map<V, PlanarDfsDetail<V, E>> vertexDetails;
public LowPointComparator(Map<V, PlanarDfsDetail<V, E>> vertexDetails) {
this.vertexDetails = vertexDetails;
}
@Override
public int compare(V lhs, V rhs) {
int lhsLowPoint = vertexDetails.get(lhs).lowPoint;
int rhsLowPoint = vertexDetails.get(rhs).lowPoint;
return lhsLowPoint > rhsLowPoint ? 1 : (lhsLowPoint < rhsLowPoint ? -1 : 0);
}
}
public static class DfsNumberComparator<V, E> implements Comparator<V> {
protected Map<V, PlanarDfsDetail<V, E>> vertexDetails;
public DfsNumberComparator(Map<V, PlanarDfsDetail<V, E>> vertexDetails) {
this.vertexDetails = vertexDetails;
}
@Override
public int compare(V lhs, V rhs) {
int lhsDfsNumber = vertexDetails.get(lhs).dfsNumber;
int rhsDfsNumber = vertexDetails.get(rhs).dfsNumber;
return lhsDfsNumber > rhsDfsNumber ? 1 : (lhsDfsNumber < rhsDfsNumber ? -1 : 0);
}
}
public Map<V, PlanarDfsDetail<V, E>> getVertexDetails() {
return vertexDetails;
}
public void setVertexDetails(Map<V, PlanarDfsDetail<V, E>> vertexDetails) {
this.vertexDetails = vertexDetails;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}