Statistics
| Revision:

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

History | View | Annotate | Download (10.2 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 setTopology(Topology topology) {
132
                this.topology = topology;
133
                for(int i = 0; i < jtsRules.size(); i++){
134
                        jtsRules.get(i).setTopology(topology);
135
                }
136
        }
137
        
138
        public void setTopologyErrorContainer(ITopologyErrorContainer errorContainer){
139
                super.setTopologyErrorContainer(errorContainer);
140
                Iterator<ITopologyRule> iterator = jtsRules.iterator();
141
                while(iterator.hasNext()){
142
                        ITopologyRule rule = iterator.next();
143
                        rule.setTopologyErrorContainer(this.errorContainer);
144
                }
145
        }
146
        
147
        private void initialize() {
148
                try {
149
                        int shapeType = this.getOriginLyr().getShapeType();
150
                        
151
                        switch(shapeType){
152
                        case FShape.POINT:
153
                        case FShape.TEXT:
154
                        case FShape.MULTIPOINT:
155
                                jtsRules.add(getValidCoordsRule());
156
                                break;
157
                        
158
                        
159
                        case FShape.ARC:
160
                        case FShape.CIRCLE:
161
                        case FShape.ELLIPSE:
162
                        case FShape.LINE:
163
                                jtsRules.add(getValidCoordsRule());
164
                                jtsRules.add(getFewPointsRule());
165
                                break;
166
                                
167
                        
168
                        case FShape.MULTI://If type is multi, it will have all rules
169
                                jtsRules.add(getValidCoordsRule());
170
                                jtsRules.add(getFewPointsRule());
171
                                jtsRules.add(getClosedRingsRule());
172
                                jtsRules.add(getHolesInShellRule());
173
                                jtsRules.add(getHolesNotNestedRule());
174
                                jtsRules.add(getIntersectingRingsRule());
175
                                jtsRules.add(getNestedShellsRule());
176
                                jtsRules.add(getNotDuplicatedRingsRule());
177
                                jtsRules.add(getSelfIntersectingRingRule());
178
                                
179
                        break;
180
                        
181
                        case FShape.POLYGON://polygon geometries wont check for nested shells
182
                                jtsRules.add(getValidCoordsRule());
183
                                jtsRules.add(getFewPointsRule());
184
                                jtsRules.add(getClosedRingsRule());
185
                                jtsRules.add(getHolesInShellRule());
186
                                jtsRules.add(getHolesNotNestedRule());
187
                                jtsRules.add(getIntersectingRingsRule());
188
                                jtsRules.add(getNotDuplicatedRingsRule());
189
                                jtsRules.add(getSelfIntersectingRingRule());
190
                                break;
191
                        
192
                        case FShape.NULL:
193
                                return;
194
                }
195
                        
196
                } catch (ReadDriverException e) {
197
                        logger.error("Error initializing JTS valid rule. "+
198
                                        "Couldnt read shape type of layer", e);
199
                }
200
        }
201
        
202
        
203
        private GeometryMustHaveValidCoordinates getValidCoordsRule(){
204
                GeometryMustHaveValidCoordinates rule = new GeometryMustHaveValidCoordinates(topology, originLyr);
205
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
206
                rule.setParentRule(this);
207
                return rule;
208
        }
209
        
210
        private GeometryMustNotHaveFewPoints getFewPointsRule(){
211
                GeometryMustNotHaveFewPoints rule = new GeometryMustNotHaveFewPoints(topology, originLyr);
212
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
213
                rule.setParentRule(this);
214
                return rule;
215
                
216
        }
217
        
218
        private IGeometryMustBeClosed getClosedRingsRule(){
219
                IGeometryMustBeClosed rule = new IGeometryMustBeClosed(topology, originLyr, snapTolerance);
220
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
221
                rule.setParentRule(this);
222
                return rule;
223
        }
224
        
225
        private MultiPolygonMustNotHaveNestedShells getNestedShellsRule(){
226
                MultiPolygonMustNotHaveNestedShells rule = 
227
                        new MultiPolygonMustNotHaveNestedShells(topology, originLyr);
228
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
229
                rule.setParentRule(this);
230
                return rule;
231
                
232
        }
233
        
234
        private PolygonHolesMustBeInShell getHolesInShellRule(){
235
                PolygonHolesMustBeInShell rule = new PolygonHolesMustBeInShell(topology, originLyr, snapTolerance);
236
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
237
                rule.setParentRule(this);
238
                return rule;        
239
        }
240
        
241
        private PolygonHolesMustNotBeNested getHolesNotNestedRule(){
242
                PolygonHolesMustNotBeNested rule = new PolygonHolesMustNotBeNested(topology, originLyr);
243
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
244
                rule.setParentRule(this);
245
                return rule;
246
        }
247
        
248
        private PolygonMustNotHaveDuplicatedRings getNotDuplicatedRingsRule(){
249
                PolygonMustNotHaveDuplicatedRings rule = 
250
                        new PolygonMustNotHaveDuplicatedRings(topology, originLyr, snapTolerance);
251
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
252
                rule.setParentRule(this);
253
                return rule;
254
        }
255
        
256
        private PolygonMustHaveConnectedInterior getIntersectingRingsRule(){
257
                PolygonMustHaveConnectedInterior rule = new PolygonMustHaveConnectedInterior(topology, originLyr);
258
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
259
                rule.setParentRule(this);
260
                return rule;
261
        }
262
        
263
        private PolygonMustNotHaveSelfIntersectedRings getSelfIntersectingRingRule(){
264
                PolygonMustNotHaveSelfIntersectedRings rule = new PolygonMustNotHaveSelfIntersectedRings(topology, originLyr, snapTolerance);
265
                rule.setTopologyErrorContainer(this.getTopologyErrorContainer());
266
                rule.setParentRule(this);
267
                return rule;
268
        }
269
        
270
        
271
        public void validateFeature(IFeature feature) {
272
                 Iterator<ITopologyRule> it = this.jtsRules.iterator();
273
                 while(it.hasNext()){
274
                         ITopologyRule rule = it.next();
275
                         rule.validateFeature(feature);
276
                 }
277
        }
278

    
279
        public String getName() {
280
                return ruleName;
281
        }
282
        /*
283
         * This rule accepts point, line and polygon layers.
284
         *  TODO Maybe must we check for getNumGeometries() > 0
285
         * for layer??
286
         * 
287
         * */
288
        public void checkPreconditions() {
289
        }
290
        
291
        public XMLEntity getXMLEntity(){
292
                XMLEntity xml = super.getXMLEntity();
293
                xml.putProperty("numberOfRules", jtsRules.size());
294
                Iterator<ITopologyRule> rulesIt = jtsRules.iterator();
295
                while(rulesIt.hasNext()){
296
                        ITopologyRule rule = rulesIt.next();
297
                        xml.addChild(rule.getXMLEntity());
298
                }
299
                return xml;
300
        }
301
            
302
        public void setXMLEntity(XMLEntity xml){
303
                super.setXMLEntity(xml);
304
                if(xml.contains("numberOfRules")){
305
                        int numberOfRules = xml.getIntProperty("numberOfRules");
306
                        for(int i = 0; i < numberOfRules; i++){
307
                                XMLEntity subRuleXML = xml.getChild(i);
308
                                //TODO Incluir llamada a RuleFactory y add(rule)
309
                                ITopologyRule rule = TopologyRuleFactory.createFromXML(topology, subRuleXML);
310
                                jtsRules.add(rule);
311
                        }//for
312
                }//if
313
        }
314

    
315
        public double getClusterTolerance() {
316
                return this.snapTolerance;
317
        }
318

    
319
        public void setClusterTolerance(double clusterTolerance) {
320
                this.snapTolerance = clusterTolerance;
321
                initialize();
322
        }
323
}
324