Statistics
| Revision:

root / trunk / libraries / libTopology / src / org / gvsig / topology / topologyrules / JtsValidRule.java @ 18253

History | View | Annotate | Download (9.82 KB)

1
/*
2
 * Created on 07-sep-2007
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
 */
50
package org.gvsig.topology.topologyrules;
51

    
52
import java.util.ArrayList;
53
import java.util.Iterator;
54
import java.util.List;
55

    
56
import org.apache.log4j.Logger;
57
import org.gvsig.topology.AbstractTopologyRule;
58
import org.gvsig.topology.IRuleWithClusterTolerance;
59
import org.gvsig.topology.ITopologyErrorContainer;
60
import org.gvsig.topology.ITopologyRule;
61
import org.gvsig.topology.Messages;
62
import org.gvsig.topology.Topology;
63
import org.gvsig.topology.TopologyRuleFactory;
64
import org.gvsig.topology.topologyrules.jtsisvalidrules.GeometryMustHaveValidCoordinates;
65
import org.gvsig.topology.topologyrules.jtsisvalidrules.GeometryMustNotHaveFewPoints;
66
import org.gvsig.topology.topologyrules.jtsisvalidrules.IGeometryMustBeClosed;
67
import org.gvsig.topology.topologyrules.jtsisvalidrules.MultiPolygonMustNotHaveNestedShells;
68
import org.gvsig.topology.topologyrules.jtsisvalidrules.PolygonHolesMustBeInShell;
69
import org.gvsig.topology.topologyrules.jtsisvalidrules.PolygonHolesMustNotBeNested;
70
import org.gvsig.topology.topologyrules.jtsisvalidrules.PolygonMustHaveConnectedInterior;
71
import org.gvsig.topology.topologyrules.jtsisvalidrules.PolygonMustNotHaveDuplicatedRings;
72
import org.gvsig.topology.topologyrules.jtsisvalidrules.PolygonMustNotHaveSelfIntersectedRings;
73

    
74
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
75
import com.iver.cit.gvsig.fmap.core.FShape;
76
import com.iver.cit.gvsig.fmap.core.IFeature;
77
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
78
import com.iver.utiles.XMLEntity;
79

    
80
/**
81
 * Any validated geometry must be a right JTS geometry.
82
 * 
83
 * A JTS geometry to be valid must check:
84
 * <ul>
85
 * <li>Must pass IsValidOp.</li>
86
 * <li>Polygon's shells must not selfintersect.</li>
87
 * <li>Polygon's holes must not selfintersect.</li>
88
 * <li>Polygon's rings must be closed.</li>
89
 * <li>Polygon's with only three collinear points are not allowed
90
 *  (this is a collapsed polygon to a line)</li>
91
 * <li>Polygon's shell must have coordinates in CCW</li>
92
 * <li>Polygon's holes must have coordinates in CCCW</li>
93
 * <li>Polygon's holes must not touch in more than one point</li>
94
 * <li>Polygon's holes could not be null</li>
95
 * <li>Polygon's holes must be contained by polygon shell</li>
96
 * <li>If a polygon has its exterior ring to null, but it has a hole, probably
97
   the order of the coordinates must be inverted.</li>
98
   <li>A polygon must not have repeated holes</li>
99
   <li>A polyline cant have two equals points.
100
   </ul>
101
 *
102
 */
103
public class JtsValidRule extends AbstractTopologyRule implements IRuleWithClusterTolerance {
104

    
105
        private static String ruleName = Messages.getText("must_be_jts_valid");
106
        
107
        private static Logger logger = Logger.getLogger(JtsValidRule.class.getName());
108
        
109
        List<ITopologyRule> jtsRules = new ArrayList<ITopologyRule>();
110
        
111
        
112
        private double snapTolerance;
113
        
114
        
115
        public JtsValidRule(FLyrVect originLyr, double snapTolerance){
116
                this(null, originLyr, snapTolerance);
117
        }
118
        
119
        public JtsValidRule(){}
120
        
121
        public JtsValidRule(Topology topology, FLyrVect originLyr, double snapTolerance){
122
                super(topology, originLyr);
123
                setClusterTolerance(snapTolerance);
124
        }
125
        
126
        public void setOriginLyr(FLyrVect originLyr){
127
                super.setOriginLyr(originLyr);
128
                initialize();
129
        }
130
        
131
        public void setTopologyErrorContainer(ITopologyErrorContainer errorContainer){
132
                super.setTopologyErrorContainer(errorContainer);
133
                Iterator<ITopologyRule> iterator = jtsRules.iterator();
134
                while(iterator.hasNext()){
135
                        ITopologyRule rule = iterator.next();
136
                        rule.setTopologyErrorContainer(this.errorContainer);
137
                }
138
        }
139
        
140
        private void initialize() {
141
                try {
142
                        int shapeType = this.getOriginLyr().getShapeType();
143
                        
144
                        switch(shapeType){
145
                        case FShape.POINT:
146
                        case FShape.TEXT:
147
                        case FShape.MULTIPOINT:
148
                                jtsRules.add(getValidCoordsRule());
149
                                break;
150
                        
151
                        
152
                        case FShape.ARC:
153
                        case FShape.CIRCLE:
154
                        case FShape.ELLIPSE:
155
                        case FShape.LINE:
156
                                jtsRules.add(getValidCoordsRule());
157
                                jtsRules.add(getFewPointsRule());
158
                                break;
159
                                
160
                        
161
                        case FShape.MULTI://If type is multi, it will have all rules
162
                                jtsRules.add(getValidCoordsRule());
163
                                jtsRules.add(getFewPointsRule());
164
                                jtsRules.add(getClosedRingsRule());
165
                                jtsRules.add(getHolesInShellRule());
166
                                jtsRules.add(getHolesNotNestedRule());
167
                                jtsRules.add(getIntersectingRingsRule());
168
                                jtsRules.add(getNestedShellsRule());
169
                                jtsRules.add(getNotDuplicatedRingsRule());
170
                                jtsRules.add(getSelfIntersectingRingRule());
171
                                
172
                        break;
173
                        
174
                        case FShape.POLYGON://polygon geometries wont check for nested shells
175
                                jtsRules.add(getValidCoordsRule());
176
                                jtsRules.add(getFewPointsRule());
177
                                jtsRules.add(getClosedRingsRule());
178
                                jtsRules.add(getHolesInShellRule());
179
                                jtsRules.add(getHolesNotNestedRule());
180
                                jtsRules.add(getIntersectingRingsRule());
181
                                jtsRules.add(getNotDuplicatedRingsRule());
182
                                jtsRules.add(getSelfIntersectingRingRule());
183
                                break;
184
                        
185
                        case FShape.NULL:
186
                                return;
187
                }
188
                        
189
                } catch (ReadDriverException e) {
190
                        logger.error("Error initializing JTS valid rule. "+
191
                                        "Couldnt read shape type of layer", e);
192
                }
193
        }
194
        
195
        
196
        private GeometryMustHaveValidCoordinates getValidCoordsRule(){
197
                GeometryMustHaveValidCoordinates rule = new GeometryMustHaveValidCoordinates(topology, originLyr);
198
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
199
                return rule;
200
        }
201
        
202
        private GeometryMustNotHaveFewPoints getFewPointsRule(){
203
                GeometryMustNotHaveFewPoints rule = new GeometryMustNotHaveFewPoints(topology, originLyr);
204
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
205
                return rule;
206
                
207
        }
208
        
209
        private IGeometryMustBeClosed getClosedRingsRule(){
210
                IGeometryMustBeClosed rule = new IGeometryMustBeClosed(topology, originLyr, snapTolerance);
211
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
212
                return rule;
213
        }
214
        
215
        private MultiPolygonMustNotHaveNestedShells getNestedShellsRule(){
216
                MultiPolygonMustNotHaveNestedShells rule = 
217
                        new MultiPolygonMustNotHaveNestedShells(topology, originLyr);
218
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
219
                return rule;
220
                
221
        }
222
        
223
        private PolygonHolesMustBeInShell getHolesInShellRule(){
224
                PolygonHolesMustBeInShell rule = new PolygonHolesMustBeInShell(topology, originLyr, snapTolerance);
225
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
226
                return rule;        
227
        }
228
        
229
        private PolygonHolesMustNotBeNested getHolesNotNestedRule(){
230
                PolygonHolesMustNotBeNested rule = new PolygonHolesMustNotBeNested(topology, originLyr);
231
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
232
                return rule;
233
        }
234
        
235
        private PolygonMustNotHaveDuplicatedRings getNotDuplicatedRingsRule(){
236
                PolygonMustNotHaveDuplicatedRings rule = 
237
                        new PolygonMustNotHaveDuplicatedRings(topology, originLyr, snapTolerance);
238
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
239
                return rule;
240
        }
241
        
242
        private PolygonMustHaveConnectedInterior getIntersectingRingsRule(){
243
                PolygonMustHaveConnectedInterior rule = new PolygonMustHaveConnectedInterior(topology, originLyr);
244
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
245
                return rule;
246
        }
247
        
248
        private PolygonMustNotHaveSelfIntersectedRings getSelfIntersectingRingRule(){
249
                PolygonMustNotHaveSelfIntersectedRings rule = new PolygonMustNotHaveSelfIntersectedRings(topology, originLyr, snapTolerance);
250
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
251
                return rule;
252
        }
253
        
254
        
255
        public void validateFeature(IFeature feature) {
256
                 Iterator<ITopologyRule> it = this.jtsRules.iterator();
257
                 while(it.hasNext()){
258
                         ITopologyRule rule = it.next();
259
                         rule.validateFeature(feature);
260
                 }
261
        }
262

    
263
        public String getName() {
264
                return ruleName;
265
        }
266
        /*
267
         * This rule accepts point, line and polygon layers.
268
         *  TODO Maybe must we check for getNumGeometries() > 0
269
         * for layer??
270
         * 
271
         * */
272
        public void checkPreconditions() {
273
        }
274
        
275
        public XMLEntity getXMLEntity(){
276
                XMLEntity xml = super.getXMLEntity();
277
                xml.putProperty("numberOfRules", jtsRules.size());
278
                Iterator<ITopologyRule> rulesIt = jtsRules.iterator();
279
                while(rulesIt.hasNext()){
280
                        ITopologyRule rule = rulesIt.next();
281
                        xml.addChild(rule.getXMLEntity());
282
                }
283
                return xml;
284
        }
285
            
286
        public void setXMLEntity(XMLEntity xml){
287
                super.setXMLEntity(xml);
288
                if(xml.contains("numberOfRules")){
289
                        int numberOfRules = xml.getIntProperty("numberOfRules");
290
                        for(int i = 0; i < numberOfRules; i++){
291
                                XMLEntity subRuleXML = xml.getChild(i);
292
                                //TODO Incluir llamada a RuleFactory y add(rule)
293
                                ITopologyRule rule = TopologyRuleFactory.createFromXML(topology, subRuleXML);
294
                                jtsRules.add(rule);
295
                        }//for
296
                }//if
297
        }
298

    
299
        public double getClusterTolerance() {
300
                return this.snapTolerance;
301
        }
302

    
303
        public void setClusterTolerance(double clusterTolerance) {
304
                this.snapTolerance = clusterTolerance;
305
                initialize();
306
        }
307
}
308