/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2006-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.util.delaunay;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import java.util.logging.Logger;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.graph.structure.Edge;
import org.geotools.graph.structure.Graph;
import org.geotools.graph.structure.Node;
import org.geotools.graph.structure.basic.BasicGraph;
/**
*
* @author jfc173
*
* @source $URL$
*/
public class AutoClustUtils {
private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geotools.graph");
/** Creates a new instance of AutoClustUtils */
public AutoClustUtils() {
}
public static Vector findConnectedComponents(final Collection nodes, final Collection edges){
Vector components = new Vector();
Vector nodesVisited = new Vector();
Iterator nodesIt = nodes.iterator();
while (nodesIt.hasNext()){
Node next = (Node) nodesIt.next();
if (!(nodesVisited.contains(next))){
Vector componentNodes = new Vector();
Vector componentEdges = new Vector();
expandComponent(next, edges, componentNodes, componentEdges);
nodesVisited.addAll(componentNodes);
Graph component = new BasicGraph(componentNodes, componentEdges);
components.add(component);
}
}
return components;
}
private static void expandComponent(final Node node, final Collection edges, final Collection componentNodes, final Collection componentEdges){
if (componentNodes.contains(node)){
//base case. I've already expanded on node, so no need to repeat the process.
// LOGGER.fine("I've already expanded from " + node);
} else {
componentNodes.add(node);
// LOGGER.finer("Adding " + node + " to component");
Vector adjacentEdges = findAdjacentEdges(node, edges); //yes, I know node.getEdges() should do this, but this method could be out of data by the time I use this in AutoClust
adjacentEdges.trimToSize();
componentEdges.addAll(adjacentEdges);
// LOGGER.finer("Adding " + adjacentEdges + " to component");
Iterator aeIt = adjacentEdges.iterator();
while (aeIt.hasNext()){
Edge next = (Edge) aeIt.next();
// LOGGER.finer("looking at edge " + next);
Node additionalNode = next.getOtherNode(node);
// LOGGER.finer("its other node is " + additionalNode);
if (additionalNode == null){
throw new RuntimeException("I tried to get the other node of this edge " + next + " but it doesn't have " + node);
}
expandComponent(additionalNode, edges, componentNodes, componentEdges);
}
adjacentEdges.clear();
}
}
public static Vector findAdjacentEdges(final Node node, final Collection edges){
Vector ret = new Vector();
Iterator it = edges.iterator();
while (it.hasNext()){
Edge next = (Edge) it.next();
if ((next.getNodeA().equals(node)) || (next.getNodeB().equals(node))){
ret.add(next);
}
}
return ret;
}
public static DelaunayNode[] featureCollectionToNodeArray(FeatureCollection<SimpleFeatureType, SimpleFeature> fc){
FeatureIterator<SimpleFeature> iter = fc.features();
int size = fc.size();
DelaunayNode[] nodes = new DelaunayNode[size];
int index = 0;
while (iter.hasNext()){
SimpleFeature next = iter.next();
Geometry geom = (Geometry) next.getDefaultGeometry();
Point centroid;
if (geom instanceof Point){
centroid = (Point) geom;
} else {
centroid = geom.getCentroid();
}
DelaunayNode node = new DelaunayNode();
node.setCoordinate(centroid.getCoordinate());
node.setFeature(next);
if (!(arrayContains(node, nodes, index))){
nodes[index] = node;
index++;
}
}
DelaunayNode[] trimmed = new DelaunayNode[index];
for (int i = 0; i < index; i++){
trimmed[i] = nodes[i];
}
return trimmed;
}
public static boolean arrayContains(DelaunayNode node, DelaunayNode[] nodes, int index){
boolean ret = false;
boolean done = false;
int i = 0;
while (!(done)){
if (i < index){
done = ret = (nodes[i].equals(node));
i++;
} else {
done = true;
}
}
return ret;
}
}