Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libTopology / src / org / gvsig / topology / topologyrules / jtsisvalidrules / PolygonHolesMustNotBeNested.java @ 18995

History | View | Annotate | Download (8.52 KB)

1 14442 azabala
/*
2
 * Created on 10-abr-2006
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
 *
46
 * $Id:
47
 * $Log:
48
 */
49
package org.gvsig.topology.topologyrules.jtsisvalidrules;
50
51 16256 azabala
import java.awt.geom.Point2D;
52
import java.util.ArrayList;
53
import java.util.HashMap;
54
import java.util.List;
55
56
import org.gvsig.fmap.core.FGeometryUtil;
57 14442 azabala
import org.gvsig.jts.JtsUtil;
58
import org.gvsig.topology.AbstractTopologyRule;
59
import org.gvsig.topology.Messages;
60 16256 azabala
import org.gvsig.topology.Topology;
61 14442 azabala
import org.gvsig.topology.TopologyError;
62
import org.gvsig.topology.TopologyRuleDefinitionException;
63 18995 azabala
import org.gvsig.topology.topologyrules.JtsValidRule;
64 14442 azabala
65 16256 azabala
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
66
import com.iver.cit.gvsig.fmap.core.FShape;
67 14442 azabala
import com.iver.cit.gvsig.fmap.core.IFeature;
68
import com.iver.cit.gvsig.fmap.core.IGeometry;
69 16256 azabala
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
70
import com.vividsolutions.jts.algorithms.SnapCGAlgorithms;
71 14442 azabala
import com.vividsolutions.jts.geom.Coordinate;
72
import com.vividsolutions.jts.geom.Geometry;
73
import com.vividsolutions.jts.geom.GeometryCollection;
74
import com.vividsolutions.jts.geom.LinearRing;
75
import com.vividsolutions.jts.geom.MultiPolygon;
76
import com.vividsolutions.jts.geom.Polygon;
77
import com.vividsolutions.jts.geomgraph.GeometryGraph;
78 16256 azabala
import com.vividsolutions.jts.precision.EnhancedPrecisionOp;
79 14442 azabala
80
public class PolygonHolesMustNotBeNested extends AbstractTopologyRule {
81 16256 azabala
82 18995 azabala
        private JtsValidRule parentRule;
83
84 16256 azabala
        public PolygonHolesMustNotBeNested(FLyrVect originLyr){
85
                super(originLyr);
86
        }
87
88
        public PolygonHolesMustNotBeNested(Topology topology, FLyrVect originLyr){
89
                super(topology, originLyr);
90
        }
91
92 16396 azabala
        public PolygonHolesMustNotBeNested(){
93
94
        }
95
96 18253 azabala
        public String getName() {
97 14442 azabala
                return Messages.getText("POLYGON_MUST_NOT_HAVE_DUPLICATED_RINGS");
98
        }
99
100
        public void checkPreconditions() throws TopologyRuleDefinitionException {
101 16256 azabala
                int shapeType;
102
                try {
103
                        shapeType = this.originLyr.getShapeType();
104
                        int numDimensions = FGeometryUtil.getDimensions(shapeType);
105
                        if(numDimensions != 2)
106
                                throw new TopologyRuleDefinitionException("HolesNotNested solo aplica sobre capas de dimension 2");
107
                } catch (ReadDriverException e) {
108
                        throw new TopologyRuleDefinitionException(
109
                                        "Error al tratar de verificar el tipo de geometria");
110
                }
111 14442 azabala
        }
112
113
        public void validateFeature(IFeature feature) {
114 16256 azabala
                Geometry jtsGeo  = FGeometryUtil.toJtsPolygon((FShape)feature.getGeometry().getInternalShape());
115 14442 azabala
                if (jtsGeo instanceof Polygon) {
116 16256 azabala
                        checkHoles((Polygon)jtsGeo, new GeometryGraph(0, jtsGeo), feature);
117 14442 azabala
                } else if (jtsGeo instanceof MultiPolygon) {
118
                        MultiPolygon multiPoly = (MultiPolygon)jtsGeo;
119
                        for(int i = 0; i < multiPoly.getNumGeometries(); i++){
120
                                Polygon polygon = (Polygon) multiPoly.getGeometryN(i);
121 16256 azabala
                                checkHoles( polygon, new GeometryGraph(0, polygon), feature);
122 14442 azabala
                        }
123
                }else if(jtsGeo instanceof GeometryCollection){
124
                        MultiPolygon multiPoly = JtsUtil.convertIfPossible((GeometryCollection) jtsGeo);
125
                        for(int i = 0; i < multiPoly.getNumGeometries(); i++){
126
                                Polygon polygon = (Polygon) multiPoly.getGeometryN(i);
127 16256 azabala
                                checkHoles( polygon, new GeometryGraph(0, polygon), feature);
128 14442 azabala
                        }
129
                }
130
        }
131
132 16256 azabala
        private void checkHoles(Polygon p, GeometryGraph graph, IFeature feature) {
133
                /*
134
                 * Holes only can touch in a single point.
135
                 * If this condition is not passed, we wont check for nested holes
136
                 */
137
                boolean disjointHoles = true;
138
139
                class MapEntry {
140
                        int i;
141
                        int j;
142
143
                        MapEntry(int i, int j){
144
                                this.i = i;
145
                                this.j = j;
146
                        }
147
148
                        public boolean equals(Object o){
149
                                if(! (o instanceof MapEntry))
150
                                        return false;
151
                                MapEntry other = (MapEntry)o;
152
153
                                return (other.i == i && other.j == j) || (other.i == j && other.j == i);
154
                        }
155
156
                        public int hashCode(){
157
                                return 1;
158
                        }
159 14442 azabala
                }
160 16256 azabala
                HashMap<MapEntry, MapEntry> checkedHoles = new HashMap<MapEntry, MapEntry>();
161
162
                 for (int i = 0; i < p.getNumInteriorRing(); i++) {
163
                         LinearRing innerHole = (LinearRing) p.getInteriorRingN(i);
164
                         Polygon innerHoleAsPoly = JtsUtil.geomFactory.createPolygon(innerHole, null);
165
                         for (int j = 0; j < p.getNumInteriorRing(); j++) {
166
                                 if ( i == j)
167
                                         continue;
168
169
                                 MapEntry entry = new MapEntry(i, j);
170
                                 if(checkedHoles.get(entry) != null)
171
                                         continue;
172
173
                                 checkedHoles.put(entry, entry);
174
175
                                 LinearRing testHole = (LinearRing) p.getInteriorRingN(j);
176
                                 Polygon testHoleAsPoly = JtsUtil.geomFactory.createPolygon(testHole, null);
177
                                 //TODO Use PreparedGeometry in the next stable release of JTS
178
                                 Geometry intersection = EnhancedPrecisionOp.intersection(innerHoleAsPoly, testHoleAsPoly);
179
                                 Coordinate[] intersectionCoords = intersection.getCoordinates();
180
                                 if(intersectionCoords.length > 1){
181
                                         disjointHoles = false;
182
                                         Point2D[] pt2d = FGeometryUtil.getCoordinatesAsPoint2D(intersectionCoords);
183
                                         IGeometry errorGeometry = FGeometryUtil.createFPolygon(pt2d);
184
                                         addError(errorGeometry, feature);
185
                                 }
186
                         }//for i
187
                 }//for j
188
189
                 if(! disjointHoles)
190
                         return;
191
192
193
                /*
194
                 * Holes must not be nested (a hole inside a hole)
195
                 * */
196
                 List<Coordinate> insidePoints = new ArrayList<Coordinate>();
197
                 for (int i = 0; i < p.getNumInteriorRing(); i++) {
198
                      LinearRing innerHole = (LinearRing) p.getInteriorRingN(i);
199
                      Coordinate[] innerHolePts = innerHole.getCoordinates();
200
                      for (int j = 0; j < p.getNumInteriorRing(); j++) {
201
                        // don't test hole against itself!
202
                        if (i == j) continue;
203
204
                        LinearRing searchHole = (LinearRing) p.getInteriorRingN(j);
205
                        // if envelopes don't overlap, holes are not nested
206
                        if (! innerHole.getEnvelopeInternal().intersects(searchHole.getEnvelopeInternal()))
207
                          continue;
208
209
                        Coordinate[] searchHolePts = searchHole.getCoordinates();
210
                        Coordinate innerholePt = JtsUtil.findPtNotNode(innerHolePts, searchHole, graph);
211
212
                        boolean inside = SnapCGAlgorithms.isPointInRing(innerholePt, searchHolePts);
213
                        if ( inside ) {
214
                                 insidePoints.add(innerholePt);
215
                        }//if
216
217
                      }//for j
218
                      if(insidePoints.size() > 0){
219
                          Coordinate[] coords = new Coordinate[insidePoints.size()];
220
                              insidePoints.toArray(coords);
221
                              Point2D[] pt2d = FGeometryUtil.getCoordinatesAsPoint2D(coords);
222
                              IGeometry geometry = FGeometryUtil.createFPolygon(pt2d);
223
                              addError(geometry, feature);
224
                        }
225
226
                    }//for i
227
//                 if (!isNonNested) {
228
//                                IFeature[] features = {feature};
229
//                                Coordinate nestedPoint = nestedTester.getNestedPoint();
230
//                                FPoint2D pt = new FPoint2D(nestedPoint.x, nestedPoint.y);
231
//                                IGeometry errorGeometry = ShapeFactory.createGeometry(pt);
232
//                                TopologyError error = new TopologyError(errorGeometry, this, features);
233
//                                addTopologyError(error);
234
//                        }
235 14442 azabala
        }
236 16256 azabala
237
238
        private void addError(IGeometry geo, IFeature feature){
239 18995 azabala
                AbstractTopologyRule violatedRule = null;
240
                if(this.parentRule != null)
241
                        violatedRule = parentRule;
242
                else
243
                        violatedRule = this;
244 16320 azabala
              TopologyError error =
245 18995 azabala
                      new TopologyError(geo, violatedRule, feature, topology);
246 16256 azabala
              addTopologyError(error);
247
        }
248 18995 azabala
249
        public JtsValidRule getParentRule() {
250
                return parentRule;
251
        }
252
253
        public void setParentRule(JtsValidRule parentRule) {
254
                this.parentRule = parentRule;
255
        }
256 14442 azabala
}