/***************************************************** * created: 10.July.2008 * last modified: * * * @author sstein * * description: * TODO * *****************************************************/ package org.openjump.core.graph.polygongraph; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.openjump.core.apitools.FeatureCollectionTools; import org.openjump.core.geomutils.algorithm.GeometryConverter; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.index.SpatialIndex; import com.vividsolutions.jts.index.strtree.STRtree; import com.vividsolutions.jump.feature.AttributeType; import com.vividsolutions.jump.feature.BasicFeature; import com.vividsolutions.jump.feature.Feature; import com.vividsolutions.jump.feature.FeatureCollection; import com.vividsolutions.jump.feature.FeatureDataset; import com.vividsolutions.jump.feature.FeatureSchema; import com.vividsolutions.jump.task.TaskMonitor; public class PolygonGraph{ public ArrayList<PolygonGraphEdge> edges = new ArrayList<PolygonGraphEdge>(); public ArrayList<PolygonGraphNode> nodes = new ArrayList<PolygonGraphNode>(); /** * creates a new polygon graph objects and populates it with the feature delivered * @param polygonFeatures */ public PolygonGraph(Collection<Feature> polygonFeatures){ this.createPolygonGraphFrom(polygonFeatures, null); } /** * creates a new polygon graph objects and populates it with the feature delivered * @param polygonFeatures * @param monitor can be null, used to cancel operation */ public PolygonGraph(Collection<Feature> polygonFeatures, TaskMonitor monitor){ this.createPolygonGraphFrom(polygonFeatures, monitor); } public PolygonGraph(FeatureCollection polygonFeatures){ this.createPolygonGraphFrom(polygonFeatures.getFeatures(), null); } /** * * @param fc * @param monitor can be null, used to cancel operation */ public void createPolygonGraphFrom(Collection<Feature> fc, TaskMonitor monitor){ //---------------------------------------------- // check if this are really polygons // if yes create a PolygonGraphNode // and add the node to a STRtree for faster search //---------------------------------------------- SpatialIndex tree = new STRtree(); for (Iterator iterator = fc.iterator(); iterator.hasNext();) { Feature f = (Feature) iterator.next(); if(f.getGeometry() instanceof Polygon){ //-- create a new node PolygonGraphNode node = new PolygonGraphNode(f); this.nodes.add(node); tree.insert(f.getGeometry().getEnvelopeInternal(), node); } else if(f.getGeometry() instanceof MultiPolygon){ //must be else if !!! Geometry geom = f.getGeometry(); //-- explode and add ArrayList<Geometry> parts = GeometryConverter.explodeGeomsIfMultiG(geom); for (Iterator iterator2 = parts.iterator(); iterator2.hasNext();) { Geometry gpart = (Geometry) iterator2.next(); Feature fnew = FeatureCollectionTools.copyFeature(f); fnew.setGeometry(gpart); //-- create a new node PolygonGraphNode node = new PolygonGraphNode(fnew); this.nodes.add(node); tree.insert(gpart.getEnvelopeInternal(), node); } } } if (monitor != null){ if (monitor.isCancelRequested()){ monitor.report("canceled 1"); return; } } //-------------------------------------------- // analyze relations // note: updating the nodes with its relations should // work as we hopefully work only with pointers //-------------------------------------------- for (Iterator iterator2 = nodes.iterator(); iterator2.hasNext();) { PolygonGraphNode node = (PolygonGraphNode) iterator2.next(); Geometry geom = node.geometry; //-- search all Polygons/nodes in the surrounding //-- get candidates List candidates = tree.query(geom.getEnvelopeInternal()); //-- check those for touching or overlapping for (Iterator iterator = candidates.iterator(); iterator.hasNext();) { PolygonGraphNode ntemp = (PolygonGraphNode) iterator.next(); //-- check if we did not retrieve the polygon itself if(ntemp.nodeId == node.nodeId){ //-- don't do anything //System.out.println("found itself"); } //-- check if connection already exists (from an earlier test) else if(node.hasConnection(ntemp)){ //System.out.println("connection exists already"); } else{ //System.out.println("calculate relation: node 1" + node.nodeId + " with node " + ntemp.nodeId); //IntersectionMatrix mat = geom.relate((ntemp.geometry); if (geom.disjoint((ntemp.geometry)) == false){ //System.out.println("found connected: node 1" + node.nodeId + " with node " + ntemp.nodeId); //-- make a new edge and add the edge to both nodes PolygonGraphEdge edge = new PolygonGraphEdge(node, ntemp); //-- add the edge to both and to the edge list node.edges.add(edge); ntemp.edges.add(edge); this.edges.add(edge); } } if (monitor != null){ if (monitor.isCancelRequested()){ monitor.report("canceled 2"); return; } } }//-- end loop over candidates }//-- end loop over all nodes } public FeatureCollection getEdgesBetweenInterriorPoints(){ FeatureCollection fc = new FeatureDataset(PolygonGraphEdge.getEdgeFeatureSchema()); for (Iterator iterator = this.edges.iterator(); iterator.hasNext();) { PolygonGraphEdge edge = (PolygonGraphEdge) iterator.next(); fc.add(edge.getEdgeBetweenInterriorPointsAsFeature()); } return fc; } public FeatureCollection getNodesAsInterriorPoint(){ FeatureSchema fs = new FeatureSchema(); fs.addAttribute("Geometry", AttributeType.GEOMETRY); fs.addAttribute("nodeId", AttributeType.INTEGER); fs.addAttribute("featureId", AttributeType.INTEGER); FeatureCollection fc = new FeatureDataset(fs); for (Iterator iterator = this.nodes.iterator(); iterator.hasNext();) { PolygonGraphNode node = (PolygonGraphNode) iterator.next(); Feature f = new BasicFeature(fs); f.setAttribute("nodeId", node.nodeId); f.setAttribute("featureId", node.realWorldObject.getID()); f.setGeometry(node.geometry.getInteriorPoint()); fc.add(f); } return fc; } public FeatureCollection getSharedBoundaries(){ //--loop over all edges to retrieve only unique boundaries FeatureCollection fc = new FeatureDataset(PolygonGraphNode.getBoundaryFeatureSchema()); for (Iterator iterator = edges.iterator(); iterator.hasNext();) { PolygonGraphEdge tedge = (PolygonGraphEdge) iterator.next(); ArrayList<Feature> edgeBoundaries = tedge.getBoundariesAsFeature(); for (Iterator iterator2 = edgeBoundaries.iterator(); iterator2.hasNext();) { Feature f = (Feature) iterator2.next(); f.setAttribute(PolygonGraphNode.edgeTypeAtributeName, "shared"); } fc.addAll(edgeBoundaries); } return fc; } public FeatureCollection getNonSharedBoundaries(){ //--loop over all edges to retrieve only unique boundaries FeatureCollection fc = new FeatureDataset(PolygonGraphNode.getBoundaryFeatureSchema()); for (Iterator iterator = nodes.iterator(); iterator.hasNext();) { PolygonGraphNode tnode = (PolygonGraphNode) iterator.next(); ArrayList<Feature> nonSharedBoundaries = tnode.getNonSharedBoundariesAsFeature(); for (Iterator iterator2 = nonSharedBoundaries.iterator(); iterator2.hasNext();) { Feature f = (Feature) iterator2.next(); f.setAttribute(PolygonGraphNode.edgeTypeAtributeName, "nonshared"); } fc.addAll(nonSharedBoundaries); } return fc; } public FeatureCollection getCommonBoundaries(PolygonGraphNode node){ ArrayList<Feature> boundaries = node.retrieveSharedBoundaries(); FeatureCollection fc = new FeatureDataset(PolygonGraphNode.getBoundaryFeatureSchema()); fc.addAll(boundaries); return fc; } }