Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGeoProcessing / src / com / iver / cit / gvsig / geoprocess / impl / spatialjoin / fmap / IntersectSpatialJoinVisitor.java @ 13874

History | View | Annotate | Download (10.9 KB)

1
/*
2
 * Created on 01-mar-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: IntersectSpatialJoinVisitor.java 13874 2007-09-19 16:12:18Z jaume $
47
 * $Log$
48
 * Revision 1.3  2007-09-19 16:08:13  jaume
49
 * ReadExpansionFileException removed from this context
50
 *
51
 * Revision 1.2  2007/03/06 16:47:58  caballero
52
 * Exceptions
53
 *
54
 * Revision 1.1  2006/06/20 18:20:45  azabala
55
 * first version in cvs
56
 *
57
 * Revision 1.2  2006/06/02 18:21:28  azabala
58
 * *** empty log message ***
59
 *
60
 * Revision 1.1  2006/05/24 21:09:47  azabala
61
 * primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing
62
 *
63
 * Revision 1.4  2006/03/21 19:29:36  azabala
64
 * *** empty log message ***
65
 *
66
 * Revision 1.3  2006/03/14 18:32:46  fjp
67
 * Cambio con LayerDefinition para que sea compatible con la definici?n de tablas tambi?n.
68
 *
69
 * Revision 1.2  2006/03/07 21:01:33  azabala
70
 * *** empty log message ***
71
 *
72
 * Revision 1.1  2006/03/06 19:48:39  azabala
73
 * *** empty log message ***
74
 *
75
 * Revision 1.1  2006/03/05 19:59:47  azabala
76
 * *** empty log message ***
77
 *
78
 *
79
 */
80
package com.iver.cit.gvsig.geoprocess.impl.spatialjoin.fmap;
81

    
82
import java.util.ArrayList;
83
import java.util.Iterator;
84
import java.util.Map;
85

    
86
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
87
import com.hardcode.gdbms.engine.values.Value;
88
import com.hardcode.gdbms.engine.values.ValueFactory;
89
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
90
import com.iver.cit.gvsig.exceptions.visitors.ProcessVisitorException;
91
import com.iver.cit.gvsig.exceptions.visitors.StartVisitorException;
92
import com.iver.cit.gvsig.exceptions.visitors.StopVisitorException;
93
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
94
import com.iver.cit.gvsig.fmap.core.IFeature;
95
import com.iver.cit.gvsig.fmap.core.IGeometry;
96
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
97
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition;
98
import com.iver.cit.gvsig.fmap.drivers.LayerDefinition;
99
import com.iver.cit.gvsig.fmap.drivers.SHPLayerDefinition;
100
import com.iver.cit.gvsig.fmap.layers.FLayer;
101
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
102
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
103
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
104
import com.iver.cit.gvsig.geoprocess.core.fmap.DefinitionUtils;
105
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureFactory;
106
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor;
107
import com.iver.cit.gvsig.geoprocess.core.fmap.SummarizationFunction;
108
import com.iver.cit.gvsig.geoprocess.core.fmap.XTypes;
109

    
110
/**
111
 * This visitor implements Intersect Geometry Spatial Join.
112
 *
113
 * It is a particular case of 1-M relationship (a feature of layer A always be
114
 * related to M feature of layer B)
115
 * It allows to apply a sumarization function over numeric values of target
116
 * layer (sum, avg, min, max). If it doesnt find any feature of target layer
117
 * wich intersects with a given feature of source layer, these values will have
118
 * 0d value.
119
 *
120
 * @author azabala
121
 *
122
 */
123
public class IntersectSpatialJoinVisitor implements SpatialJoinVisitor {
124

    
125
        /**
126
         * Needed to create layer definition
127
         */
128
        private FLyrVect sourceLayer;
129
        /**
130
         * Reads data of features for the source layer
131
         */
132
        private SelectableDataSource sourceRecordset;
133

    
134
        /**
135
         * Recordset of this layer
136
         */
137
        private SelectableDataSource targetRecordset;
138

    
139
        /**
140
         * Strategy to do querys against target Layer
141
         */
142
        private Strategy strategy;
143

    
144
        /**
145
         * Maps for each numerical field of target layer its sumarization functions
146
         */
147
        private Map fields_sumarizeFunc;
148

    
149
        /**
150
         * Visitor that finds features of target layer that intersects with a given
151
         * feature of source layer
152
         */
153
        private IntersectsFinderFeatureVisitor visitor;
154

    
155
        /**
156
         * Processes results of dissolve operations (save them in a file, or cache
157
         * them in memory, etc)
158
         */
159
        private FeatureProcessor featureProcessor;
160

    
161
        private LayerDefinition resultLayerDefinition;
162

    
163
        private boolean onlySecondLyrSelection;
164

    
165
        public IntersectSpatialJoinVisitor(FLyrVect sourceLayer,
166
                                                                                FLyrVect targetLayer,
167
                                                                                Map fields_sumarizeFunct,
168
                                                                                FeatureProcessor processor) throws ReadDriverException {
169
                this.sourceLayer = sourceLayer;
170
                this.sourceRecordset = sourceLayer.getRecordset();
171
                this.featureProcessor = processor;
172
                this.fields_sumarizeFunc = fields_sumarizeFunct;
173
                this.targetRecordset = targetLayer.getRecordset();
174
                this.visitor = new IntersectsFinderFeatureVisitor(fields_sumarizeFunc);
175
        }
176

    
177
        public void visit(IGeometry g, int index) throws VisitorException, ProcessVisitorException {
178
                if(g == null)
179
                        return;
180
                IFeature solution = null;
181
                visitor.setQueryGeometry(g.toJTSGeometry());
182
                try {
183
                        if(onlySecondLyrSelection)
184
                                visitor.setSelection(targetRecordset.getSelection());
185
                        strategy.process(visitor, g.getBounds2D());
186
                        solution = createFeature(g, index, visitor.getNumIntersections());
187
                        featureProcessor.processFeature(solution);
188
                        resetFunctions();
189
                        visitor.clearIntersections();
190
                } catch (ReadDriverException e) {
191
                        throw new ProcessVisitorException(targetRecordset.getName(),e,
192
                                        "Error al buscar las intersecciones de una geometria durante un spatial join");
193
                } 
194
        }
195

    
196
        public String getProcessDescription() {
197
                return "Spatial joining by intersects criteria";
198
        }
199

    
200
        public void resetFunctions(){
201
                Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator();
202
                while (fieldsIt.hasNext()) {
203
                        String field = (String) fieldsIt.next();
204
                        SummarizationFunction[] functions =
205
                                (SummarizationFunction[]) fields_sumarizeFunc.get(field);
206
                        for (int i = 0; i < functions.length; i++) {
207
                                functions[i].reset();
208
                        }// for
209
                }// while
210
        }
211

    
212

    
213
        private IFeature createFeature(IGeometry g, int index, int numIntersections)
214
                        throws ReadDriverException {
215
                IFeature solution = null;
216
                int numSourceFields = this.sourceRecordset.getFieldCount();
217
                ArrayList values = new ArrayList();
218
                for (int i = 0; i < numSourceFields; i++) {
219
                        values.add(sourceRecordset.getFieldValue(index, i));
220
                }
221
                //target layer
222
                Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator();
223
                while (fieldsIt.hasNext()) {
224
                        String field = (String) fieldsIt.next();
225
                        SummarizationFunction[] functions =
226
                                (SummarizationFunction[]) fields_sumarizeFunc.get(field);
227
                        for (int i = 0; i < functions.length; i++) {
228
                                values.add(functions[i].getSumarizeValue());
229
                        }// for
230
                }// while
231
                values.add(ValueFactory.createValue(numIntersections));
232
                Value[] attrs = new Value[values.size()];
233
                values.toArray(attrs);
234
                solution = FeatureFactory.createFeature(attrs, g);
235
                return solution;
236
        }
237

    
238
        public void stop(FLayer layer) throws StopVisitorException {
239
                featureProcessor.finish();
240

    
241
        }
242

    
243
        public boolean start(FLayer layer) throws StartVisitorException {
244
                this.featureProcessor.start();
245
                return true;
246
        }
247

    
248

    
249
        public ILayerDefinition getResultLayerDefinition(){
250
                if(this.resultLayerDefinition == null){
251
                        ArrayList fields = new ArrayList();
252
                        resultLayerDefinition = new SHPLayerDefinition();
253
                        //result layer will be exactly similar to firstLayer with
254
                        //new attributes
255
                        try {
256
                                resultLayerDefinition.setShapeType(sourceLayer.getShapeType());
257
                        } catch (ReadDriverException e) {
258
                                // TODO Auto-generated catch block
259
                                e.printStackTrace();
260
                        }
261

    
262
                        //first layer attributes
263
                        int numFields = 0;
264
                        try {
265
                                numFields = sourceRecordset.getFieldCount();
266
                        } catch (ReadDriverException e) {
267
                                // TODO Auto-generated catch block
268
                                e.printStackTrace();
269
                        }
270

    
271
                        FieldDescription fieldDesc = null;
272
                        for(int i = 0; i < numFields; i++){
273
                                fieldDesc = new FieldDescription();
274
                                try {
275
                                        fieldDesc.setFieldName(sourceRecordset.getFieldName(i));
276
                                        int fieldType = sourceRecordset.getFieldType(i);
277
                                        fieldDesc.setFieldType(fieldType);
278
                                        fieldDesc.setFieldLength(DefinitionUtils.
279
                                                        getDataTypeLength(fieldType));
280
                                        fieldDesc.setFieldDecimalCount(DefinitionUtils.NUM_DECIMALS);
281
                                } catch (ReadDriverException e) {
282
                                        // TODO Auto-generated catch block
283
                                        e.printStackTrace();
284
                                }
285
                                fields.add(fieldDesc);
286
                        }//for
287

    
288
                        //target layer attributes
289
                        Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator();
290
                        while(fieldsIt.hasNext()){
291
                                String field = (String) fieldsIt.next();
292
                                SummarizationFunction[] functions =
293
                                        (SummarizationFunction[]) fields_sumarizeFunc.get(field);
294
                                for(int i = 0; i < functions.length; i++){
295
                                        fieldDesc = new FieldDescription();
296
//                                        to avoid truncation of field names (f.example shp)
297
                                        //we only catch three first letters
298
                                        String shortName = null;
299
                                        if(field.length() > 3)
300
                                                shortName = field.substring(0,3);
301
                                        else
302
                                                shortName = field;
303
                                        fieldDesc.setFieldName(
304
                                                        shortName + "_" + functions[i].toString());
305
                                        fieldDesc.setFieldType(XTypes.DOUBLE);
306
                                        int fieldLenght = DefinitionUtils.getDataTypeLength(XTypes.DOUBLE);
307
                                        fieldDesc.setFieldLength(fieldLenght);
308
                                        fieldDesc.setFieldDecimalCount(DefinitionUtils.NUM_DECIMALS);
309
                                        fields.add(fieldDesc);
310
                                }//for
311
                        }//while
312

    
313
                        //finally, we add to the result schema of M-N spatial join
314
                        //the number of features intersected of layer b
315
                        fieldDesc = new FieldDescription();
316
                        fieldDesc.setFieldName("NUM_RELA");
317
                        fieldDesc.setFieldType(XTypes.INTEGER);
318
                        fieldDesc.setFieldLength(DefinitionUtils.
319
                                        getDataTypeLength(XTypes.INTEGER));
320
                        fields.add(fieldDesc);
321

    
322
                        FieldDescription[] fieldsDesc = null;
323
                        if(fields.size() == 0){
324
                                fieldsDesc = new FieldDescription[0];
325
                        }else{
326
                                fieldsDesc = new FieldDescription[fields.size()];
327
                                fields.toArray(fieldsDesc);
328
                        }
329
                        resultLayerDefinition.setFieldsDesc(fieldsDesc);
330
                }//if result == null
331
                return resultLayerDefinition;
332
        }
333

    
334
        public void setFeatureProcessor(FeatureProcessor processor) {
335
                this.featureProcessor = processor;
336
        }
337

    
338
        public void setCancelableStrategy(Strategy secondLyrStrategy) {
339
                this.strategy = secondLyrStrategy;
340
        }
341

    
342
        public void setOnlySecondLyrSelection(boolean onlySecondLayerSelection) {
343
                this.onlySecondLyrSelection = onlySecondLayerSelection;
344
        }
345

    
346
}