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