/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is 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
* Lesser General Public License for more details.
*/
package org.geotools.graph.build.line;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.geotools.graph.structure.Edge;
import org.geotools.graph.structure.Graphable;
import org.geotools.graph.structure.Node;
import org.geotools.graph.structure.line.OptDirectedXYNode;
import org.geotools.graph.structure.opt.OptDirectedNode;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineSegment;
/**
* An implementation of GraphGenerator used to generate an optimized graph
* representing a line network. Graphs are generated by supplying the generator
* with objects of type LineSegment via the add(Object) method. <BR>
* <BR>
* For each line segment added, an edge in the graph is created. The builder
* records the end coordinates of each line added, and maintains a map of
* coordinates to nodes, creating nodes when neccessary.<BR>
* <BR>
* Edges created by the generator are of type OptBasicEdge.
* Nodes created by the generator are of type OptXYNode.
*
* @see org.geotools.graph.structure.opt.OptEdge
* @see org.geotools.graph.structure.line.OptXYNode
*
* @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net
*
* @source $URL$
*/
public class OptDirectedLineGraphGenerator extends OptLineGraphGenerator {
/** maps in coordinates to count / node **/
HashMap m_in2count;
/** maps out coordinates to count / node **/
HashMap m_out2count;
/**
* Constructs a new OptLineGraphGenerator.
*/
public OptDirectedLineGraphGenerator() {
super();
m_in2count = new HashMap();
m_out2count = new HashMap();
setGraphBuilder(new OptDirectedLineGraphBuilder());
}
/**
* Adds a line to the graph. Note that this method returns null since actual
* building of the graph components is delayed until generate() is called.
*
* @param obj A LineSegment object.
*
* @return null because the actual building of the graph components is delayed
* until generate() is called.
*/
public Graphable add(Object obj) {
LineSegment line = (LineSegment)obj;
Integer count;
//increment the count of the in coordinate
if ((count = (Integer)m_in2count.get(line.p0)) == null) {
m_in2count.put(line.p0, new Integer(1));
}
else m_in2count.put(line.p0, new Integer(count.intValue()+1));
//increment the count of the out coordinate
if ((count = (Integer)m_out2count.get(line.p1)) == null) {
m_out2count.put(line.p1, new Integer(1));
}
else m_out2count.put(line.p1, new Integer(count.intValue()+1));
getLines().add(line);
return(null);
}
/**
* Returns the coordinate to <B>in</B> node map. Note that before the call to
* generate the map does not contain any nodes.
*
* @return Coordinate to in node map.
*/
public Map getInNodeMap() {
return(m_in2count);
}
/**
* Returns the coordinate to <B>out</B> node map. Note that before the call to
* generate the map does not contain any nodes.
*
* @return Coordinate to out node map.
*/
public Map getOutNodeMap() {
return(m_out2count);
}
protected void generateNodes() {
//create the nodes, starting with in nodes
for (Iterator itr = m_in2count.entrySet().iterator(); itr.hasNext();) {
Map.Entry entry = (Map.Entry)itr.next();
Coordinate coord = (Coordinate)entry.getKey();
Integer count = (Integer)entry.getValue();
OptDirectedXYNode node = (OptDirectedXYNode)getGraphBuilder().buildNode();
node.setCoordinate(coord);
//set the out degree (in count means => out degree)
node.setOutDegree(count.intValue());
//get the in degree (out count) from the out map, if no entry, set to 0
count = (Integer)m_out2count.get(coord);
if (count != null) node.setInDegree(count.intValue());
else node.setInDegree(0);
getGraphBuilder().addNode(node);
//set map value to be node instead of count
entry.setValue(node);
}
//create only nodes that are not in the in set
for (Iterator itr = m_out2count.entrySet().iterator(); itr.hasNext();) {
Map.Entry entry = (Map.Entry)itr.next();
Coordinate coord = (Coordinate)entry.getKey();
Integer count = (Integer)entry.getValue();
//look for the node in the in set, if not there, it means that the
// node is never an in node => out degree = 0
OptDirectedXYNode node = (OptDirectedXYNode)m_in2count.get(coord);
if (node == null) {
node = (OptDirectedXYNode)getGraphBuilder().buildNode();
node.setCoordinate(coord);
node.setOutDegree(0);
node.setInDegree(count.intValue());
getGraphBuilder().addNode(node);
}
//else do nothing, the node was already set when processing in set
//set map value to be node instead of count
entry.setValue(node);
}
}
protected Edge generateEdge(LineSegment line) {
OptDirectedNode n1 = (OptDirectedNode)m_in2count.get(line.p0);
OptDirectedNode n2 = (OptDirectedNode)m_out2count.get(line.p1);
Edge edge = getGraphBuilder().buildEdge(n1,n2);
getGraphBuilder().addEdge(edge);
return(edge);
}
public Node getNode(Coordinate c) {
Node n = (Node)m_in2count.get(c);
if (n != null) return(n);
return((Node)m_out2count.get(c));
}
public Edge getEdge(Coordinate c1, Coordinate c2) {
//TODO: IMPLEMENT
return(null);
}
}