com.vividsolutions.jts.noding.IteratedNoder Maven / Gradle / Ivy
/*
* The JTS Topology Suite is a collection of Java classes that
* implement the fundamental operations required to validate a given
* geo-spatial data set to a known topological specification.
*
* Copyright (C) 2001 Vivid Solutions
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For more information, contact:
*
* Vivid Solutions
* Suite #1A
* 2328 Government Street
* Victoria BC V8T 5G5
* Canada
*
* (250)385-6040
* www.vividsolutions.com
*/
package com.vividsolutions.jts.noding;
import com.vividsolutions.jts.algorithm.*;
import com.vividsolutions.jts.geom.*;
import java.util.*;
/**
* Nodes a set of {@link NodedSegmentString}s completely.
* The set of segment strings is fully noded;
* i.e. noding is repeated until no further
* intersections are detected.
*
* Iterated noding using a FLOATING precision model is not guaranteed to converge,
* due to roundoff error.
* This problem is detected and an exception is thrown.
* Clients can choose to rerun the noding using a lower precision model.
*
* @version 1.7
*/
public class IteratedNoder
implements Noder
{
public static final int MAX_ITER = 5;
private PrecisionModel pm;
private LineIntersector li;
private Collection nodedSegStrings;
private int maxIter = MAX_ITER;
public IteratedNoder(PrecisionModel pm)
{
li = new RobustLineIntersector();
this.pm = pm;
li.setPrecisionModel(pm);
}
/**
* Sets the maximum number of noding iterations performed before
* the noding is aborted.
* Experience suggests that this should rarely need to be changed
* from the default.
* The default is MAX_ITER.
*
* @param maxIter the maximum number of iterations to perform
*/
public void setMaximumIterations(int maxIter)
{
this.maxIter = maxIter;
}
public Collection getNodedSubstrings() { return nodedSegStrings; }
/**
* Fully nodes a list of {@link SegmentString}s, i.e. peforms noding iteratively
* until no intersections are found between segments.
* Maintains labelling of edges correctly through
* the noding.
*
* @param segStrings a collection of SegmentStrings to be noded
* @throws TopologyException if the iterated noding fails to converge.
*/
public void computeNodes(Collection segStrings)
throws TopologyException
{
int[] numInteriorIntersections = new int[1];
nodedSegStrings = segStrings;
int nodingIterationCount = 0;
int lastNodesCreated = -1;
do {
node(nodedSegStrings, numInteriorIntersections);
nodingIterationCount++;
int nodesCreated = numInteriorIntersections[0];
/**
* Fail if the number of nodes created is not declining.
* However, allow a few iterations at least before doing this
*/
//System.out.println("# nodes created: " + nodesCreated);
if (lastNodesCreated > 0
&& nodesCreated >= lastNodesCreated
&& nodingIterationCount > maxIter) {
throw new TopologyException("Iterated noding failed to converge after "
+ nodingIterationCount + " iterations");
}
lastNodesCreated = nodesCreated;
} while (lastNodesCreated > 0);
//System.out.println("# nodings = " + nodingIterationCount);
}
/**
* Node the input segment strings once
* and create the split edges between the nodes
*/
private void node(Collection segStrings, int[] numInteriorIntersections)
{
IntersectionAdder si = new IntersectionAdder(li);
MCIndexNoder noder = new MCIndexNoder();
noder.setSegmentIntersector(si);
noder.computeNodes(segStrings);
nodedSegStrings = noder.getNodedSubstrings();
numInteriorIntersections[0] = si.numInteriorIntersections;
//System.out.println("# intersection tests: " + si.numTests);
}
}