Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libGeocoding / src / org / gvsig / geocoding / styles / impl / DoubleRange.java @ 28375

History | View | Annotate | Download (13.2 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 Prodevelop S.L. main development
26
 */
27

    
28
package org.gvsig.geocoding.styles.impl;
29

    
30
import java.util.ArrayList;
31
import java.util.List;
32
import java.util.Set;
33
import java.util.TreeSet;
34

    
35
import org.gvsig.fmap.dal.exception.DataException;
36
import org.gvsig.fmap.dal.feature.Feature;
37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.primitive.Point;
39
import org.gvsig.fmap.geom.util.Converter;
40
import org.gvsig.geocoding.address.Address;
41
import org.gvsig.geocoding.address.Literal;
42
import org.gvsig.geocoding.address.NumberAddress;
43
import org.gvsig.geocoding.address.RelationsComponent;
44
import org.gvsig.geocoding.address.impl.DefaultAddressComponent;
45
import org.gvsig.geocoding.address.impl.DefaultLiteral;
46
import org.gvsig.geocoding.address.impl.DefaultNumberAddress;
47
import org.gvsig.geocoding.geommatches.MatcherUtils;
48
import org.gvsig.geocoding.result.GeocodingResult;
49
import org.gvsig.geocoding.result.ScoredFeature;
50
import org.gvsig.geocoding.result.impl.GeomMatchResult;
51
import org.gvsig.tools.persistence.PersistenceException;
52
import org.gvsig.tools.persistence.PersistentState;
53
import org.slf4j.Logger;
54
import org.slf4j.LoggerFactory;
55

    
56
/**
57
 * Implemented Geocoding style with search by numerical range. This style geocodes streets
58
 * with even numbers on one side of the street and odd numbers on other side.
59
 * 
60
 * @author <a href="mailto:jsanz@prodevelop.es"> Jorge Gaspar Sanz Salinas</a>
61
 * @author <a href="mailto:vsanjaime@prodevelop.es"> Vicente Sanjaime Calvet</a>
62
 */
63

    
64
public class DoubleRange extends AbstractRange {
65

    
66
        private static final Logger log = LoggerFactory
67
                        .getLogger(DoubleRange.class);
68

    
69
        private static final String FIRSTLEFTNUMBER = "firstleftnumber";
70
        private static final String FIRSTRIGHTNUMBER = "firstrightnumber";
71
        private static final String LASTLEFTNUMBER = "lastleftnumber";
72
        private static final String LASTRIGHTNUMBER = "firstrightnumber";
73

    
74
        private RelationsComponent firstLeftNumber;
75
        private RelationsComponent firstRightNumber;
76
        private RelationsComponent lastLeftNumber;
77
        private RelationsComponent lastRightNumber;
78

    
79
        /**
80
         * Get relation component that define the field of data source that it has
81
         * the first left number of the feature
82
         * 
83
         * @return
84
         */
85
        public RelationsComponent getFirstLeftNumber() {
86
                return firstLeftNumber;
87
        }
88

    
89
        /**
90
         * Set relation component that define the field of data source that it has
91
         * the first left number of the feature
92
         * 
93
         * @param firstLeftNumber
94
         */
95
        public void setFirstLeftNumber(RelationsComponent firstLeftNumber) {
96
                this.firstLeftNumber = firstLeftNumber;
97
        }
98

    
99
        /**
100
         * Get relation component that define the field of data source that it has
101
         * the first right number of the feature
102
         * 
103
         * @return
104
         */
105
        public RelationsComponent getFirstRightNumber() {
106
                return firstRightNumber;
107
        }
108

    
109
        /**
110
         * Set relation component that define the field of data source that it has
111
         * the first right number of the feature
112
         * 
113
         * @param firstRightNumber
114
         */
115
        public void setFirstRightNumber(RelationsComponent firstRightNumber) {
116
                this.firstRightNumber = firstRightNumber;
117
        }
118

    
119
        /**
120
         * Get relation component that define the field of data source that it has
121
         * the last left number of the feature
122
         * 
123
         * @return
124
         */
125
        public RelationsComponent getLastLeftNumber() {
126
                return lastLeftNumber;
127
        }
128

    
129
        /**
130
         * Set relation component that define the field of data source that it has
131
         * the last left number of the feature
132
         * 
133
         * @param lastLeftNumber
134
         */
135
        public void setLastLeftNumber(RelationsComponent lastLeftNumber) {
136
                this.lastLeftNumber = lastLeftNumber;
137
        }
138

    
139
        /**
140
         * Get relation component that define the field of data source that it has
141
         * the last right number of the feature
142
         * 
143
         * @return
144
         */
145
        public RelationsComponent getLastRightNumber() {
146
                return lastRightNumber;
147
        }
148

    
149
        /**
150
         * Set relation component that define the field of data source that it has
151
         * the last right number of the feature
152
         * 
153
         * @param lastRightNumber
154
         */
155
        public void setLastRightNumber(RelationsComponent lastRightNumber) {
156
                this.lastRightNumber = lastRightNumber;
157
        }
158

    
159
        /**
160
         * Spatial search over the geometries of the selected features
161
         * 
162
         * @param lists
163
         *            list of lists with ScoredFeatures
164
         * @param address
165
         * @return
166
         */
167
        @Override
168
        public Set<GeocodingResult> match(List<List<ScoredFeature>> inLists,
169
                        Address address) {
170

    
171
                Set<GeocodingResult> results = new TreeSet<GeocodingResult>();
172

    
173
                String firstLeftNumberDesc = this.getFirstLeftNumber().getValue();
174
                String lastLeftNumberDesc = this.getLastLeftNumber().getValue();
175
                String firstRightNumberDesc = this.getFirstRightNumber().getValue();
176
                String lastRightNumberDesc = this.getLastRightNumber().getValue();
177

    
178
                // get the list
179
                List<ScoredFeature> sFeats = inLists.get(0);
180
                if (sFeats.size() > 0) {
181
                        int number = ((NumberAddress) address).getNumber();
182

    
183
                        try {
184
                                for (ScoredFeature sFeat : sFeats) {
185

    
186
                                        Feature fea = sFeat.getFeature();
187

    
188
                                        int[] range = getNumberRange(fea, firstLeftNumberDesc,
189
                                                        lastLeftNumberDesc, firstRightNumberDesc,
190
                                                        lastRightNumberDesc);
191
                                        int firstL = range[0];
192
                                        int lastL = range[1];
193
                                        int firstR = range[2];
194
                                        int lastR = range[3];
195

    
196
                                        // Number even (Par)
197
                                        if (number % 2 == 0) {
198
                                                // Left numbers - EVEN // right numbers - ODD
199
                                                if (firstL % 2 == 0) {
200
                                                        if (number >= firstL && number <= lastL) {
201
                                                                // create result
202
                                                                GeomMatchResult res = calculatePosition(sFeat,
203
                                                                                number, firstL, lastL);
204
                                                                // add result to the list
205
                                                                results.add(res);
206
                                                        }
207
                                                }
208
                                                // Left numbers - ODD // right numbers - EVEN
209
                                                else {
210
                                                        if (number >= firstR && number <= lastR) {
211
                                                                // create result
212
                                                                GeomMatchResult res = calculatePosition(sFeat,
213
                                                                                number, firstR, lastR);
214
                                                                // add result to the list
215
                                                                results.add(res);
216
                                                        }
217
                                                }
218
                                        }
219
                                        // number odd (Impar)
220
                                        else {
221
                                                // Left numbers - EVEN // right numbers - ODD
222
                                                if (firstL % 2 == 0) {
223
                                                        if (number >= firstR && number <= lastR) {
224
                                                                // create result
225
                                                                GeomMatchResult res = calculatePosition(sFeat,
226
                                                                                number, firstR, lastR);
227
                                                                // add result to the list
228
                                                                results.add(res);
229
                                                        }
230
                                                }
231
                                                // Left numbers - ODD // right numbers - EVEN
232
                                                else {
233
                                                        if (number >= firstL && number <= lastL) {
234
                                                                // create result
235
                                                                GeomMatchResult res = calculatePosition(sFeat,
236
                                                                                number, firstL, lastL);
237
                                                                // add result to the list
238
                                                                results.add(res);
239
                                                        }
240
                                                }
241
                                        }
242
                                }
243
                        } catch (DataException e) {
244
                                log.error("Error getting the features", e);
245
                        }
246
                }
247
                return results;
248
        }
249

    
250
        /**
251
         * Calculate the relative distance in line
252
         * 
253
         * @param number
254
         * @param first
255
         * @param last
256
         * @return
257
         */
258
        private int calculateRelativeDistance(int number, int first, int last) {
259
                if (first == last) {
260
                        return 50;
261
                }
262
                int total = Math.abs(last - first);
263
                int ini = Math.abs(number - first);
264
                return (ini * 100) / total;
265
        }
266

    
267
        /**
268
         * Calculate the position
269
         * 
270
         * @param feat
271
         * @param number
272
         * @param first
273
         * @param last
274
         * @return
275
         * @throws DataException
276
         */
277
        private GeomMatchResult calculatePosition(ScoredFeature feat, int number,
278
                        int first, int last) throws DataException {
279

    
280
                Geometry geom = feat.getReference().getFeature().getDefaultGeometry();
281
                com.vividsolutions.jts.geom.Geometry geJTS = Converter
282
                                .geometryToJts(geom);
283
                int relative = calculateRelativeDistance(number, first, last);
284
                Point position = MatcherUtils.getLinePositionFromRelativeDistance(
285
                                geJTS, relative);
286
                // create result
287
                GeomMatchResult res = new GeomMatchResult();
288
                List<ScoredFeature> list = new ArrayList<ScoredFeature>();
289
                list.add(feat);
290
                res.setGeom(position);
291
                res.setMainSources(list);
292
                res.setAddress(getResultAddress(list, number));
293

    
294
                return res;
295
        }
296

    
297
        /**
298
         * Calculate the position with a offset positive or negative
299
         * 
300
         * @param feat
301
         * @param number
302
         * @param first
303
         * @param last
304
         * @param offset
305
         * @return
306
         * @throws DataException
307
         */
308
        private GeomMatchResult calculateOffsetPosition(ScoredFeature feat,
309
                        int number, int first, int last, int offset) throws DataException {
310

    
311
                Geometry geom = feat.getReference().getFeature().getDefaultGeometry();
312
                com.vividsolutions.jts.geom.Geometry geJTS = Converter
313
                                .geometryToJts(geom);
314
                int relative = calculateRelativeDistance(number, first, last);
315
                Point position = MatcherUtils.getLinePositionFromRelativeDistance(
316
                                geJTS, relative);
317
                // create result
318
                GeomMatchResult res = new GeomMatchResult();
319
                List<ScoredFeature> list = new ArrayList<ScoredFeature>();
320
                list.add(feat);
321
                res.setGeom(position);
322
                res.setMainSources(list);
323
                res.setAddress(getResultAddress(list, number));
324
                return res;
325
        }
326

    
327
        /**
328
         * 
329
         * @param feat
330
         * @return
331
         */
332
        private int[] getNumberRange(Feature feat, String firstRightNumberDesc,
333
                        String lastRightNumberDesc, String firstLeftNumberDesc,
334
                        String lastLeftNumberDesc) {
335

    
336
                int[] range = new int[4];
337

    
338
                Object oRFirst = feat.get(firstRightNumberDesc);
339
                Object oRLast = feat.get(lastRightNumberDesc);
340
                Object oLFirst = feat.get(firstLeftNumberDesc);
341
                Object oLLast = feat.get(lastLeftNumberDesc);
342

    
343
                // RIGHT FIRST
344
                if (oRFirst instanceof Double) {
345
                        range[0] = ((Double) oRFirst).intValue();
346
                }
347
                if (oRFirst instanceof Integer) {
348
                        range[0] = ((Integer) oRFirst).intValue();
349
                }
350
                if (oRFirst instanceof String) {
351
                        range[0] = Integer.parseInt(((String) oRFirst));
352
                }
353
                // RIGHT LAST
354
                if (oRLast instanceof Double) {
355
                        range[1] = ((Double) oRLast).intValue();
356
                }
357
                if (oRLast instanceof Integer) {
358
                        range[1] = ((Integer) oRLast).intValue();
359
                }
360
                if (oRLast instanceof String) {
361
                        range[1] = Integer.parseInt(((String) oRLast));
362
                }
363
                // LEFT FIRST
364
                if (oLFirst instanceof Double) {
365
                        range[2] = ((Double) oLFirst).intValue();
366
                }
367
                if (oLFirst instanceof Integer) {
368
                        range[2] = ((Integer) oLFirst).intValue();
369
                }
370
                if (oLFirst instanceof String) {
371
                        range[2] = Integer.parseInt(((String) oLFirst));
372
                }
373
                // LEFT LAST
374
                if (oLLast instanceof Double) {
375
                        range[3] = ((Double) oLLast).intValue();
376
                }
377
                if (oLLast instanceof Integer) {
378
                        range[3] = ((Integer) oLLast).intValue();
379
                }
380
                if (oLLast instanceof String) {
381
                        range[3] = Integer.parseInt(((String) oLLast));
382
                }
383

    
384
                return range;
385
        }
386

    
387
        /**
388
         * 
389
         * @return
390
         */
391
        private Address getResultAddress(List<ScoredFeature> sources, int number) {
392

    
393
                // get the first element
394
                ScoredFeature feat = sources.get(0);
395

    
396
                Literal relLiteral = this.getRelationsLiteral();
397
                Literal literal = new DefaultLiteral();
398
                for (Object obj : relLiteral) {
399
                        RelationsComponent rel = (RelationsComponent) obj;
400
                        String key = rel.getKeyElement();
401
                        String fieldName = rel.getValue();
402
                        Object object = null;
403
                        String value = "";
404
                        try {
405
                                object = feat.getFeature().get(fieldName);
406
                                value = object.toString();
407
                        } catch (DataException e) {
408
                                log.error("Getting attributes ot the feature", e);
409
                        }
410
                        literal.add(new DefaultAddressComponent(key, value));
411
                }
412

    
413
                NumberAddress address = new DefaultNumberAddress();
414
                address.setMainLiteral(literal);
415
                address.setNumber(number);
416
                return address;
417
        }
418

    
419
        /**
420
         * Saves the internal state of the object on the provided PersistentState
421
         * object.
422
         * 
423
         * @param state
424
         */
425
        public void saveToState(PersistentState state) throws PersistenceException {
426
                super.saveToState(state);
427
                state.set(FIRSTLEFTNUMBER, this.firstLeftNumber);
428
                state.set(FIRSTRIGHTNUMBER, this.firstRightNumber);
429
                state.set(LASTLEFTNUMBER, this.lastLeftNumber);
430
        }
431

    
432
        /**
433
         * Set the state of the object from the state passed as parameter.
434
         * 
435
         * @param state
436
         */
437
        public void setState(PersistentState state) throws PersistenceException {
438
                super.setState(state);
439
                this.firstLeftNumber = (RelationsComponent) state.get(FIRSTLEFTNUMBER);
440
                this.firstRightNumber = (RelationsComponent) state
441
                                .get(FIRSTRIGHTNUMBER);
442
                this.lastLeftNumber = (RelationsComponent) state.get(LASTLEFTNUMBER);
443
                this.lastRightNumber = (RelationsComponent) state.get(LASTRIGHTNUMBER);
444
        }
445

    
446
}