package prefuse.action.filter;
import java.util.Iterator;
import prefuse.Constants;
import prefuse.Visualization;
import prefuse.action.GroupAction;
import prefuse.data.Graph;
import prefuse.data.expression.Predicate;
import prefuse.data.tuple.TupleSet;
import prefuse.data.util.BreadthFirstIterator;
import prefuse.data.util.FilterIterator;
import prefuse.util.PrefuseLib;
import prefuse.visual.VisualItem;
import prefuse.visual.expression.InGroupPredicate;
/**
* Filter Action that sets visible all items within a specified graph distance
* from a set of focus items; all other items will be set to invisible.
*
* @author <a href="http://jheer.org">jeffrey heer</a>
*/
public class GraphDistanceFilter extends GroupAction {
protected int m_distance;
protected String m_sources;
protected Predicate m_groupP;
protected BreadthFirstIterator m_bfs;
/**
* Create a new GraphDistanceFilter that processes the given data group
* and uses a graph distance of 1. By default, the
* {@link prefuse.Visualization#FOCUS_ITEMS} group will be used as the
* source nodes from which to measure the distance.
* @param group the group to process. This group should resolve to a
* Graph instance, otherwise exceptions will be thrown when this
* Action is run.
*/
public GraphDistanceFilter(String group) {
this(group, 1);
}
/**
* Create a new GraphDistanceFilter that processes the given data group
* and uses the given graph distance. By default, the
* {@link prefuse.Visualization#FOCUS_ITEMS} group will be used as the
* source nodes from which to measure the distance.
* @param group the group to process. This group should resolve to a
* Graph instance, otherwise exceptions will be thrown when this
* Action is run.
* @param distance the graph distance within which items will be
* visible.
*/
public GraphDistanceFilter(String group, int distance) {
this(group, Visualization.FOCUS_ITEMS, distance);
}
/**
* Create a new GraphDistanceFilter that processes the given data group
* and uses the given graph distance.
* @param group the group to process. This group should resolve to a
* Graph instance, otherwise exceptions will be thrown when this
* Action is run.
* @param sources the group to use as source nodes for measuring
* graph distance.
* @param distance the graph distance within which items will be
* visible.
*/
public GraphDistanceFilter(String group, String sources, int distance)
{
super(group);
m_sources = sources;
m_distance = distance;
m_groupP = new InGroupPredicate(
PrefuseLib.getGroupName(group, Graph.NODES));
m_bfs = new BreadthFirstIterator();
}
/**
* Return the graph distance threshold used by this filter.
* @return the graph distance threshold
*/
public int getDistance() {
return m_distance;
}
/**
* Set the graph distance threshold used by this filter.
* @param distance the graph distance threshold to use
*/
public void setDistance(int distance) {
m_distance = distance;
}
/**
* Get the name of the group to use as source nodes for measuring
* graph distance. These form the roots from which the graph distance
* is measured.
* @return the source data group
*/
public String getSources() {
return m_sources;
}
/**
* Set the name of the group to use as source nodes for measuring
* graph distance. These form the roots from which the graph distance
* is measured.
* @param sources the source data group
*/
public void setSources(String sources) {
m_sources = sources;
}
/**
* @see prefuse.action.GroupAction#run(double)
*/
public void run(double frac) {
// mark the items
Iterator items = m_vis.visibleItems(m_group);
while ( items.hasNext() ) {
VisualItem item = (VisualItem)items.next();
item.setDOI(Constants.MINIMUM_DOI);
}
// set up the graph traversal
TupleSet src = m_vis.getGroup(m_sources);
Iterator srcs = new FilterIterator(src.tuples(), m_groupP);
m_bfs.init(srcs, m_distance, Constants.NODE_AND_EDGE_TRAVERSAL);
// traverse the graph
while ( m_bfs.hasNext() ) {
VisualItem item = (VisualItem)m_bfs.next();
int d = m_bfs.getDepth(item);
PrefuseLib.updateVisible(item, true);
item.setDOI(-d);
item.setExpanded(d < m_distance);
}
// mark unreached items
items = m_vis.visibleItems(m_group);
while ( items.hasNext() ) {
VisualItem item = (VisualItem)items.next();
if ( item.getDOI() == Constants.MINIMUM_DOI ) {
PrefuseLib.updateVisible(item, false);
item.setExpanded(false);
}
}
}
} // end of class GraphDistanceFilter