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: * Created on Apr 27, 2004
018: */
019: package org.geotools.validation.relate;
020:
021: import java.io.IOException;
022: import java.util.Map;
023: import java.util.logging.Logger;
024:
025: import org.geotools.feature.FeatureIterator;
026: import org.geotools.feature.FeatureCollection;
027: import org.geotools.data.FeatureSource;
028: import org.geotools.feature.Feature;
029: import org.geotools.filter.Filter;
030: import org.geotools.filter.FilterFactory;
031: import org.geotools.filter.FilterFactoryFinder;
032: import org.geotools.validation.ValidationResults;
033:
034: import com.vividsolutions.jts.geom.Envelope;
035: import com.vividsolutions.jts.geom.Geometry;
036:
037: /**
038: * @author Pati
039: *
040: * <b>Puropse:</b><br>
041: * <p>
042: * Tests to see if a Geometry touches another Geometry.
043: *
044: * <b>Description:</b><br>
045: * <p>
046: * If only one Geometry is given, then this test checks to see if it
047: * touches to itself.
048: * </p>
049: *
050: * <b>Usage:</b><br>
051: * <p>
052: *
053: * </p>
054: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/extension/validation/src/main/java/org/geotools/validation/relate/TouchesIntegrity.java $
055: */
056: public class TouchesIntegrity extends RelationIntegrity {
057: private static final Logger LOGGER = org.geotools.util.logging.Logging
058: .getLogger("org.geotools.validation");
059:
060: /**
061: * OverlapsIntegrity Constructor
062: *
063: */
064: public TouchesIntegrity() {
065: super ();
066: }
067:
068: /* (non-Javadoc)
069: * @see org.geotools.validation.IntegrityValidation#validate(java.util.Map, com.vividsolutions.jts.geom.Envelope, org.geotools.validation.ValidationResults)
070: */
071: public boolean validate(Map layers, Envelope envelope,
072: ValidationResults results) throws Exception {
073: LOGGER.finer("Starting test " + getName() + " ("
074: + getClass().getName() + ")");
075: String typeRef1 = getGeomTypeRefA();
076: LOGGER.finer(typeRef1 + ": looking up FeatureSource ");
077: FeatureSource geomSource1 = (FeatureSource) layers
078: .get(typeRef1);
079: LOGGER.finer(typeRef1 + ": found "
080: + geomSource1.getSchema().getTypeName());
081:
082: String typeRef2 = getGeomTypeRefB();
083: if (typeRef2 == EMPTY || typeRef1.equals(typeRef2))
084: return validateSingleLayer(geomSource1, isExpected(),
085: results, envelope);
086: else {
087: LOGGER.finer(typeRef2 + ": looking up FeatureSource ");
088: FeatureSource geomSource2 = (FeatureSource) layers
089: .get(typeRef2);
090: LOGGER.finer(typeRef2 + ": found "
091: + geomSource2.getSchema().getTypeName());
092: return validateMultipleLayers(geomSource1, geomSource2,
093: isExpected(), results, envelope);
094: }
095:
096: }
097:
098: /**
099: * <b>validateMultipleLayers Purpose:</b> <br>
100: * <p>
101: * This validation tests for a geometry touches another geometry.
102: * Uses JTS' Geometry.touches(Geometry) method.
103: * Returns true if the DE-9IM intersection matrix for the two Geometrys is FT*******, F**T***** or F***T****.
104: * </p>
105: *
106: * <b>Description:</b><br>
107: * <p>
108: * The function filters the FeatureSources using the given bounding box.
109: * It creates iterators over both filtered FeatureSources. It calls touches() using the
110: * geometries in the FeatureSource layers. Tests the results of the method call against
111: * the given expected results. Returns true if the returned results and the expected results
112: * are true, false otherwise.
113: *
114: * </p>
115: *
116: * Author: bowens<br>
117: * Created on: Apr 27, 2004<br>
118: * @param featureSourceA - the FeatureSource to pull the original geometries from.
119: * @param featureSourceB - the FeatureSource to pull the other geometries from.
120: * @param expected - boolean value representing the user's expected outcome of the test
121: * @param results - ValidationResults
122: * @param bBox - Envelope - the bounding box within which to perform the touches()
123: * @return boolean result of the test
124: * @throws Exception - IOException if iterators improperly closed
125:
126: */
127: private boolean validateMultipleLayers(
128: FeatureSource featureSourceA, FeatureSource featureSourceB,
129: boolean expected, ValidationResults results, Envelope bBox)
130: throws Exception {
131: boolean success = true;
132:
133: FilterFactory ff = FilterFactoryFinder.createFilterFactory();
134: Filter filter = null;
135:
136: //JD: fix this!!
137: //filter = (Filter) ff.createBBoxExpression(bBox);
138:
139: FeatureCollection collectionA = featureSourceA
140: .getFeatures(filter);
141: FeatureCollection collectionB = featureSourceB
142: .getFeatures(filter);
143:
144: FeatureIterator fr1 = null;
145: FeatureIterator fr2 = null;
146: try {
147: fr1 = collectionA.features();
148: if (fr1 == null)
149: return false;
150:
151: while (fr1.hasNext()) {
152: Feature f1 = fr1.next();
153: Geometry g1 = f1.getDefaultGeometry();
154: fr2 = collectionB.features();
155: try {
156: while (fr2 != null && fr2.hasNext()) {
157: Feature f2 = fr2.next();
158: Geometry g2 = f2.getDefaultGeometry();
159: if (g1.touches(g2) != expected) {
160: results.error(f1, f1.getDefaultGeometry()
161: .getGeometryType()
162: + " "
163: + getGeomTypeRefA()
164: + " touches "
165: + getGeomTypeRefB()
166: + "("
167: + f2.getID()
168: + "), Result was not " + expected);
169: success = false;
170: }
171: }
172: } finally {
173: collectionB.close(fr2);
174: }
175: }
176: } finally {
177: collectionA.close(fr1);
178: }
179:
180: return success;
181: }
182:
183: /**
184: * <b>validateSingleLayer Purpose:</b> <br>
185: * <p>
186: * This validation tests for a geometry that touches on itself.
187: * Uses JTS' Geometry.touches(Geometry) method.
188: * Returns true if the DE-9IM intersection matrix for the two Geometrys is FT*******, F**T***** or F***T****.
189: * </p>
190: *
191: * <b>Description:</b><br>
192: * <p>
193: * The function filters the FeatureSource using the given bounding box.
194: * It creates iterators over the filtered FeatureSource. It calls touches() using the
195: * geometries in the FeatureSource layer. Tests the results of the method call against
196: * the given expected results. Returns true if the returned results and the expected results
197: * are true, false otherwise.
198: *
199: * </p>
200: *
201: * Author: bowens<br>
202: * Created on: Apr 27, 2004<br>
203: * @param featureSourceA - the FeatureSource to pull the original geometries from.
204: * @param expected - boolean value representing the user's expected outcome of the test
205: * @param results - ValidationResults
206: * @param bBox - Envelope - the bounding box within which to perform the touches()
207: * @return boolean result of the test
208: * @throws Exception - IOException if iterators improperly closed
209: */
210: private boolean validateSingleLayer(FeatureSource featureSourceA,
211: boolean expected, ValidationResults results, Envelope bBox)
212: throws Exception {
213: boolean success = true;
214:
215: FilterFactory ff = FilterFactoryFinder.createFilterFactory();
216: Filter filter = null;
217:
218: //JD: fix this !!
219: //filter = (Filter) ff.createBBoxExpression(bBox);
220:
221: FeatureCollection collection = featureSourceA
222: .getFeatures(filter);
223:
224: FeatureIterator fr1 = null;
225: FeatureIterator fr2 = null;
226: try {
227: fr1 = collection.features();
228:
229: if (fr1 == null)
230: return false;
231:
232: while (fr1.hasNext()) {
233: Feature f1 = fr1.next();
234: Geometry g1 = f1.getDefaultGeometry();
235: fr2 = collection.features();
236: try {
237: while (fr2 != null && fr2.hasNext()) {
238: Feature f2 = fr2.next();
239: Geometry g2 = f2.getDefaultGeometry();
240: if (!f1.getID().equals(f2.getID())) // if they are the same feature, move onto the next one
241: {
242: if (g1.touches(g2) != expected) {
243: results.error(f1, f1
244: .getDefaultGeometry()
245: .getGeometryType()
246: + " "
247: + getGeomTypeRefA()
248: + " touches "
249: + getGeomTypeRefA()
250: + "("
251: + f2.getID()
252: + "), Result was not "
253: + expected);
254: success = false;
255: }
256: }
257: }
258: } finally {
259: collection.close(fr2);
260: }
261: }
262: } finally {
263: collection.close(fr1);
264: }
265:
266: return success;
267: }
268: }
|