001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2004 TOPP - www.openplans.org
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.validation.spatial;
018:
019: import java.util.logging.Level;
020: import java.util.logging.Logger;
021:
022: import org.geotools.feature.Feature;
023: import org.geotools.feature.FeatureType;
024: import org.geotools.validation.DefaultFeatureValidation;
025: import org.geotools.validation.ValidationResults;
026:
027: import com.vividsolutions.jts.geom.Coordinate;
028: import com.vividsolutions.jts.geom.GeometryFactory;
029: import com.vividsolutions.jts.geom.LineString;
030: import com.vividsolutions.jts.geom.Point;
031:
032: /**
033: * Ensure the defaultGeometry does not overlap (only works for LineString).
034: *
035: * <p>
036: * Tests to see if a LineString overlaps itself. It does this by breaking up
037: * the LineString into two point segments then intersects them all. If a
038: * segment has both of its points on another segment, then they overlap. This
039: * is not true in all cases and this method has to be rewritten. If a segment
040: * spans two segments, this method will say that they do not overlap when
041: * clearly they do.
042: * </p>
043: *
044: * @author bowens, Refractions Research, Inc.
045: * @author $Author: jive $ (last modification)
046: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/extension/validation/src/main/java/org/geotools/validation/spatial/LineNoSelfOverlappingValidation.java $
047: * @version $Id: LineNoSelfOverlappingValidation.java 27862 2007-11-12 19:51:19Z desruisseaux $
048: */
049: public class LineNoSelfOverlappingValidation extends
050: DefaultFeatureValidation {
051: /** The logger for the validation module. */
052: private static final Logger LOGGER = org.geotools.util.logging.Logging
053: .getLogger("org.geotools.validation");
054:
055: /**
056: * LineNoSelfOverlappingFeatureValidation constructor.
057: *
058: * <p>
059: * Description
060: * </p>
061: */
062: public LineNoSelfOverlappingValidation() {
063: System.out
064: .println("***************** LineNoSelfOverlappingValidation *************");
065: }
066:
067: /**
068: * Override getPriority.
069: *
070: * <p>
071: * Sets the priority level of this validation.
072: * </p>
073: *
074: * @return A made up priority for this validation.
075: *
076: * @see org.geotools.validation.Validation#getPriority()
077: */
078: public int getPriority() {
079: return PRIORITY_COMPLEX;
080: }
081:
082: /**
083: * Tests to see if a LineString overlaps itself.
084: *
085: * <p>
086: * It does this by breaking up the LineString into two point segments then
087: * intersects them all. If a segment has both of its points on another
088: * segment, then they overlap. This is not true in all cases and this
089: * method has to be rewritten. If a segment spans two segments, this
090: * method will say that they do not overlap when clearly they do.
091: * </p>
092: *
093: * @param feature The Feature to be validated
094: * @param type The FeatureTypeInfo of the feature
095: * @param results The storage for error messages.
096: *
097: * @return True if the feature does not overlap itself.
098: *
099: * @see org.geotools.validation.FeatureValidation#validate(org.geotools.feature.Feature,
100: * org.geotools.feature.FeatureTypeInfo,
101: * org.geotools.validation.ValidationResults)
102: */
103: public boolean validate(Feature feature, FeatureType type,
104: ValidationResults results) {
105: //BUG: refer to comments above.
106: LOGGER.setLevel(Level.ALL);
107:
108: LineString line = null;
109: try {
110: line = getDefaultLineString(feature);
111: } catch (ClassCastException unLine) {
112: results.error(feature,
113: "Geometry is required to be a LineString");
114: System.out
115: .println(feature.getID() + " name: " + getName());
116: System.out.println(feature.getID() + " ref: "
117: + getTypeRef());
118: System.out.println(feature.getID() + " ref: "
119: + getTypeRefs());
120: }
121: if (line == null) {
122: // Ignore null geometry (user can check with nullZero )
123: return true;
124: }
125: if (line.getNumPoints() < 2) {
126: results.warning(feature,
127: "LineString contains too few points");
128: return false;
129: }
130: GeometryFactory gf = new GeometryFactory();
131:
132: int numPoints = line.getNumPoints();
133:
134: // break up the LineString into line segments
135: LineString[] segments = new LineString[numPoints - 1];
136:
137: for (int i = 0; i < (numPoints - 1); i++) {
138: Coordinate[] coords = new Coordinate[] {
139: line.getCoordinateN(i), line.getCoordinateN(i + 1) };
140: segments[i] = gf.createLineString(coords);
141: }
142:
143: // overlap all of the line segments with each other
144: for (int i = 0; i < segments.length; i++) // for each line segment
145: {
146: for (int j = 0; j < segments.length; j++) // test with every other line segment
147: {
148: if ((i != j)) // if they aren't the same segment
149: {
150: if (segments[i].relate(segments[j], "1********")) // changed to relate - bowens
151: {
152: results.error(feature,
153: "LineString overlapped itself.");
154: return false;
155: }
156: }
157: }
158: }
159:
160: //LOGGER.log(Level.FINEST, getName() + "(" + feature.getID() + ") passed");
161: return true;
162: }
163:
164: /*
165: * touchesSegment
166: * iterates all segments and returns true as soon as the point is found to intersect with the linestring
167: * */
168: private boolean touchesSegment(LineString[] segments, Point p1) {
169: for (int i = 0; i < segments.length; i++) {
170: //using intersects will handle a point that is not an end point on the line segment
171: if (p1.intersects(segments[i])) {
172: return true;
173: }
174: }
175: return false;
176: }
177: }
|