/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-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.validation.spatial;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geotools.validation.DefaultFeatureValidation;
import org.geotools.validation.ValidationResults;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
/**
* LineNoSelfIntersectFeatureValidation purpose.
*
* <p>
* Tests to see if a geometry crosses itself. It does not detect if a
* segment of a LineString doubles back on itself for one segment, then
* terminates. A different validation is needed to test overlapping. Uses JTS'
* crosses routine.
* </p>
*
* <p>
* Example Use:
* <pre><code>
* LineNoSelfIntersectFeatureValidation x = new LineNoSelfIntersectFeatureValidation("noSelfIntersectRoads", "Tests to see if a
* geometry intersects itself", new String[] {"road"});
* </code></pre>
* </p>
*
* @author bowens, Refractions Research, Inc.
* @author $Author: jive $ (last modification)
* @source $URL$
* @version $Id$
* - bowens: changed intersects to crosses
*/
public class LineNoSelfIntersectValidation extends DefaultFeatureValidation {
/** The logger for the validation module. */
private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(
"org.geotools.validation");
/**
* LineNoSelfIntersectFeatureValidation constructor.
*
* <p>
* Description
* </p>
*/
public LineNoSelfIntersectValidation() {
}
/**
* Override getPriority.
*
* <p>
* Sets the priority level of this validation. This is set by the
* programmer and is a measure of the expense of this plugin
* </p>
*
* @return A made up priority for this validation.
*
* @see org.geotools.validation.Validation#getPriority()
*/
public int getPriority() {
return PRIORITY_COMPLEX;
}
/**
* Override validate.
*
* <p>
* Tests to see if a geometry intersects itself. It does not detect if a
* segment of a LineString doubles back on itself for one segment, then
* terminates. A different validation is needed to test overlapping. Uses
* JTS' intersect routine.
* </p>
*
* @param feature The Feature to be validated.
* @param type The FeatureTypeInfo of the feature.
* @param results The storage for error messages.
*
* @return True if the feature does not self intersect.
*
* @see org.geotools.validation.FeatureValidation#validate(org.geotools.feature.Feature,
* org.geotools.feature.FeatureTypeInfo,
* org.geotools.validation.ValidationResults)
*/
public boolean validate(SimpleFeature feature, SimpleFeatureType type,
ValidationResults results) {
LOGGER.setLevel(Level.ALL);
LineString line = null;
try {
line = getDefaultLineString( feature );
}
catch( ClassCastException unLine ){
results.error(feature,"Geometry is required to be a LineString");
System.out.println( feature.getID()+" name: "+getName() );
System.out.println( feature.getID()+" ref: "+getTypeRef() );
System.out.println( feature.getID()+" ref: "+getTypeRefs() );
}
if (line == null) {
// Ignore null geometry (user can check with nullZero )
return true;
}
if (line.getNumPoints() < 2) {
results.warning(feature,"LineString contains too few points");
return false;
}
GeometryFactory gf = new GeometryFactory();
int numPoints = line.getNumPoints();
// break up the LineString into line segments
LineString[] segments = new LineString[numPoints - 1];
for (int i = 0; i < (numPoints - 1); i++) {
Coordinate[] coords = new Coordinate[] {
line.getCoordinateN(i), line.getCoordinateN(i + 1)
};
segments[i] = gf.createLineString(coords);
}
// intersect all of the line segments with each other
for (int i = 0; i < segments.length; i++) // for each line segment
{
for (int j = 0; j < segments.length; j++) // intersect with every other line segment
{
if ((i != j) && ((i - 1) != j) && ((i + 1) != j)) // if they aren't the same segment
{
if (segments[i].crosses(segments[j])) // changed to crosses - bowens
{
// log the error and return
results.error(feature, "LineString crossed itself");
return false;
}
}
}
}
return true;
}
}