/*
* 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;
import com.vividsolutions.jts.geom.Point;
/**
* Ensure the defaultGeometry does not overlap (only works for LineString).
*
* <p>
* Tests to see if a LineString overlaps itself. It does this by breaking up
* the LineString into two point segments then intersects them all. If a
* segment has both of its points on another segment, then they overlap. This
* is not true in all cases and this method has to be rewritten. If a segment
* spans two segments, this method will say that they do not overlap when
* clearly they do.
* </p>
*
* @author bowens, Refractions Research, Inc.
* @author $Author: jive $ (last modification)
*
* @source $URL$
* @version $Id$
*/
public class LineNoSelfOverlappingValidation extends DefaultFeatureValidation {
/** The logger for the validation module. */
private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(
"org.geotools.validation");
/**
* LineNoSelfOverlappingFeatureValidation constructor.
*
* <p>
* Description
* </p>
*/
public LineNoSelfOverlappingValidation() {
System.out.println("***************** LineNoSelfOverlappingValidation *************");
}
/**
* Override getPriority.
*
* <p>
* Sets the priority level of this validation.
* </p>
*
* @return A made up priority for this validation.
*
* @see org.geotools.validation.Validation#getPriority()
*/
public int getPriority() {
return PRIORITY_COMPLEX;
}
/**
* Tests to see if a LineString overlaps itself.
*
* <p>
* It does this by breaking up the LineString into two point segments then
* intersects them all. If a segment has both of its points on another
* segment, then they overlap. This is not true in all cases and this
* method has to be rewritten. If a segment spans two segments, this
* method will say that they do not overlap when clearly they do.
* </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 overlap itself.
*
* @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) {
//BUG: refer to comments above.
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);
}
// overlap 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++) // test with every other line segment
{
if ((i != j)) // if they aren't the same segment
{
if (segments[i].relate(segments[j],"1********")) // changed to relate - bowens
{
results.error(feature, "LineString overlapped itself.");
return false;
}
}
}
}
//LOGGER.log(Level.FINEST, getName() + "(" + feature.getID() + ") passed");
return true;
}
/*
* touchesSegment
* iterates all segments and returns true as soon as the point is found to intersect with the linestring
* */
private boolean touchesSegment(LineString[] segments, Point p1) {
for(int i = 0; i < segments.length; i++ ) {
//using intersects will handle a point that is not an end point on the line segment
if(p1.intersects(segments[i])) {
return true;
}
}
return false;
}
}