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.Map;
020:
021: import org.geotools.data.FeatureSource;
022: import org.geotools.feature.Feature;
023: import org.geotools.feature.FeatureCollection;
024: import org.geotools.feature.FeatureIterator;
025: import org.geotools.validation.ValidationResults;
026:
027: import com.vividsolutions.jts.geom.Envelope;
028: import com.vividsolutions.jts.geom.Geometry;
029: import com.vividsolutions.jts.geom.LineString;
030: import com.vividsolutions.jts.geom.Polygon;
031:
032: /**
033: * Ensure a LineString is contained by Polygon.
034: *
035: * <p>
036: * This is an integrity test in which we ensure that every LineString in a
037: * FeatureType is contained by a Polygon in a second FeatureType. This needs
038: * to be done as an Integrity Test to account for both the LineString and
039: * Polygon FeatureTypes being changed in the same Transaction. Further more
040: * the test will need to be run if either (or both) FeatureTypes are changed:
041: * a new line may be created outside of a polygon, or a polygon may be deleted
042: * leaving a line uncovered. If we a bit smarter about these relationship we
043: * could run this Validation Test only on LineString insert/modify or Polygon
044: * modify/delete but life is too short, and there is always another release.
045: * </p>
046: *
047: * <p>
048: * To do this with any sense of efficiency we will need to take an initial run
049: * through the Polygon FeatureSource to build an Index of FeatureID by
050: * BoundingBox. We can use this to selectively query the Polygon FeatureSource
051: * as we work through the LineString content.
052: * </p>
053: *
054: * <p>
055: * TODO: David Zweirs Read This! Talk to Justin or any of the JUMP experts who
056: * have experence in implementing JTS indexes. You can use the "layers" Map to
057: * store the generated index, or make up an API to do so as part of the
058: * ValidationProcessor. At the very least your index will last for the current
059: * validation "run" - which is all that can be expected. What really needs to
060: * be done is punt the index generation off to the database/DataStore anything
061: * else won't scale (don't you love GIS problems).
062: * </p>
063: *
064: * @author Jody Garnett, Refractions Research, Inc.
065: * @author $Author: dmzwiers $ (last modification)
066: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/extension/validation/src/main/java/org/geotools/validation/spatial/LineCoveredByPolygonValidation.java $
067: * @version $Id: LineCoveredByPolygonValidation.java 22666 2006-11-09 03:50:28Z jgarnett $
068: */
069: public class LineCoveredByPolygonValidation extends
070: LinePolygonAbstractValidation {
071:
072: /**
073: * No argument constructor, required by the Java Bean Specification.
074: */
075: public LineCoveredByPolygonValidation() {
076: }
077:
078: /**
079: * Check that lineTypeRef is convered by polygonTypeRef.
080: *
081: * <p>
082: * Detailed description...
083: * </p>
084: *
085: * @param layers Map of FeatureSource by "dataStoreID:typeName"
086: * @param envelope The bounding box that encloses the unvalidated data
087: * @param results Used to coallate results information
088: *
089: * @return <code>true</code> if all the features pass this test.
090: *
091: * @throws Exception DOCUMENT ME!
092: */
093: public boolean validate(Map layers, Envelope envelope,
094: ValidationResults results) throws Exception {
095:
096: boolean r = true;
097:
098: FeatureSource fsLine = (FeatureSource) layers
099: .get(getLineTypeRef());
100:
101: FeatureCollection fcLine = fsLine.getFeatures();
102: FeatureIterator fLine = fcLine.features();
103:
104: FeatureSource fsPoly = (FeatureSource) layers
105: .get(getRestrictedPolygonTypeRef());
106:
107: FeatureCollection fcPoly = fsPoly.getFeatures();
108:
109: while (fLine.hasNext()) {
110: Feature line = fLine.next();
111: FeatureIterator fPoly = fcPoly.features();
112: Geometry lineGeom = line.getDefaultGeometry();
113: if (envelope.contains(lineGeom.getEnvelopeInternal())) {
114: // check for valid comparison
115: if (LineString.class.isAssignableFrom(lineGeom
116: .getClass())) {
117: while (fPoly.hasNext()) {
118: Feature poly = fPoly.next();
119: Geometry polyGeom = poly.getDefaultGeometry();
120: if (envelope.contains(polyGeom
121: .getEnvelopeInternal())) {
122: if (Polygon.class.isAssignableFrom(polyGeom
123: .getClass())) {
124: if (!polyGeom.contains(lineGeom)) {
125: results
126: .error(poly,
127: "Polygon does not contain the specified Line.");
128: r = false;
129: }
130: // do next.
131: } else {
132: fcPoly.remove(poly);
133: results
134: .warning(poly,
135: "Invalid type: this feature is not a derivative of a Polygon");
136: }
137: } else {
138: fcPoly.remove(poly);
139: }
140: }
141: } else {
142: results
143: .warning(line,
144: "Invalid type: this feature is not a derivative of a LineString");
145: }
146: }
147: }
148: return r;
149: }
150:
151: /**
152: * The priority level used to schedule this Validation.
153: *
154: * @return PRORITY_SIMPLE
155: *
156: * @see org.geotools.validation.Validation#getPriority()
157: */
158: public int getPriority() {
159: return PRIORITY_SIMPLE;
160: }
161: }
|