Statistics
| Revision:

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

History | View | Annotate | Download (8.83 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 and odd numbers followed.
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 SimpleRange extends AbstractRange {
65

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

    
69
        private static final String FIRSTNUMBER = "firstnumber";
70
        private static final String LASTNUMBER = "lastnumber";
71

    
72
        private RelationsComponent firstNumber;
73
        private RelationsComponent lastNumber;
74

    
75
        /**
76
         * Set relation component that define the field of data source that it has
77
         * the first number of the feature
78
         * 
79
         * @return
80
         */
81
        public RelationsComponent getFirstNumber() {
82
                return firstNumber;
83
        }
84

    
85
        /**
86
         * Set relation component that define the field of data source that it has
87
         * the first number of the feature
88
         * 
89
         * @param firstNumber
90
         */
91
        public void setFirstNumber(RelationsComponent firstNumber) {
92
                this.firstNumber = firstNumber;
93
        }
94

    
95
        /**
96
         * get relation component that define the field of data source that it has
97
         * the last number of the feature
98
         * 
99
         * @return
100
         */
101
        public RelationsComponent getLastNumber() {
102
                return lastNumber;
103
        }
104

    
105
        /**
106
         * Set relation component that define the field of data source that it has
107
         * the last number of the feature
108
         * 
109
         * @param lastNumber
110
         */
111
        public void setLastNumber(RelationsComponent lastNumber) {
112
                this.lastNumber = lastNumber;
113
        }
114

    
115
        /**
116
         * Spatial search over the geometries of the features selected
117
         * 
118
         * @param lists
119
         *            list of lists with ScoredFeatures
120
         * @param address
121
         * @return
122
         */
123
        @Override
124
        public Set<GeocodingResult> match(List<List<ScoredFeature>> inLists,
125
                        Address address) {
126
                Set<GeocodingResult> results = new TreeSet<GeocodingResult>();
127

    
128
                String firstNumberDesc = this.getFirstNumber().getValue();
129
                String lastNumberDesc = this.getLastNumber().getValue();
130

    
131
                // Get the list
132
                List<ScoredFeature> sFeats = inLists.get(0);
133
                if (sFeats.size() > 0) {
134
                        try {
135
                                for (ScoredFeature sFeat : sFeats) {
136

    
137
                                        int number = ((NumberAddress) address).getNumber();
138

    
139
                                        Feature fea = sFeat.getFeature();
140

    
141
                                        int[] range = getNumberRange(fea, firstNumberDesc,
142
                                                        lastNumberDesc);
143
                                        int first = range[0];
144
                                        int last = range[1];
145

    
146
                                        if (number >= first && number <= last) {
147
                                                // create result
148
                                                GeomMatchResult res = calculatePosition(sFeat, number,
149
                                                                first, last);
150
                                                // add result to the list
151
                                                results.add(res);
152
                                        }
153
                                }
154
                        } catch (DataException e) {
155
                                log.error("Error Getting the features", e);
156
                        }
157
                }
158
                return results;
159
        }
160

    
161
        /**
162
         * Calculate point over the geometry (line)
163
         * 
164
         * @param feat
165
         *            feature
166
         * @param number
167
         *            of address
168
         * @param first
169
         *            number of feature geometry
170
         * @param last
171
         *            number of feature geometry
172
         * @return
173
         * @throws DataException
174
         */
175
        private GeomMatchResult calculatePosition(ScoredFeature feat, int number,
176
                        int first, int last) throws DataException {
177

    
178
                Geometry geom = feat.getReference().getFeature().getDefaultGeometry();
179
                com.vividsolutions.jts.geom.Geometry geJTS = Converter
180
                                .geometryToJts(geom);
181
                int relative = calculateRelativeDistance(number, first, last);
182
                Point position = MatcherUtils.getLinePositionFromRelativeDistance(
183
                                geJTS, relative);
184
                // create result
185
                GeomMatchResult res = new GeomMatchResult();
186
                List<ScoredFeature> list = new ArrayList<ScoredFeature>();
187
                list.add(feat);
188
                res.setGeom(position);
189
                res.setMainSources(list);
190
                res.setAddress(getResultAddress(list, number));
191
                return res;
192
        }
193

    
194
        /**
195
         * calculate relative position over line with number of address from initial
196
         * number and last number of the geom
197
         * 
198
         * @param number
199
         *            of address
200
         * @param first
201
         *            number of geometry
202
         * @param last
203
         *            number of geometry
204
         * @return
205
         */
206
        private int calculateRelativeDistance(int number, int first, int last) {
207
                if (first == last) {
208
                        return 50;
209
                }
210
                int total = Math.abs(last - first);
211
                int ini = Math.abs(number - first);
212
                return (ini * 100) / total;
213
        }
214

    
215
        /**
216
         * Get range of the numbers (ood side or even side)
217
         * 
218
         * @param feat
219
         * @return
220
         */
221
        private int[] getNumberRange(Feature feat, String firstNumberDesc,
222
                        String lastNumberDesc) {
223

    
224
                int[] range = new int[2];
225

    
226
                Object oFirst = feat.get(firstNumberDesc);
227
                Object oLast = feat.get(lastNumberDesc);
228

    
229
                // FIRST
230
                if (oFirst instanceof Double) {
231
                        range[0] = ((Double) oFirst).intValue();
232
                }
233
                if (oFirst instanceof Integer) {
234
                        range[0] = ((Integer) oFirst).intValue();
235
                }
236
                if (oFirst instanceof String) {
237
                        range[0] = Integer.parseInt(((String) oFirst));
238
                }
239
                // LAST
240
                if (oLast instanceof Double) {
241
                        range[1] = ((Double) oLast).intValue();
242
                }
243
                if (oLast instanceof Integer) {
244
                        range[1] = ((Integer) oLast).intValue();
245
                }
246
                if (oLast instanceof String) {
247
                        range[1] = Integer.parseInt(((String) oLast));
248
                }
249

    
250
                return range;
251
        }
252

    
253
        /**
254
         * Get result address
255
         * 
256
         * @return
257
         */
258
        private Address getResultAddress(List<ScoredFeature> sources, int number) {
259

    
260
                // get the first element
261
                ScoredFeature feat = sources.get(0);
262

    
263
                Literal relLiteral = this.getRelationsLiteral();
264
                Literal literal = new DefaultLiteral();
265
                for (Object obj : relLiteral) {
266
                        RelationsComponent rel = (RelationsComponent) obj;
267
                        String key = rel.getKeyElement();
268
                        String fieldName = rel.getValue();
269
                        Object object = null;
270
                        String value = "";
271
                        try {
272
                                object = feat.getFeature().get(fieldName);
273
                                value = object.toString();
274
                        } catch (DataException e) {
275
                                log.error("Getting attributes ot the feature", e);
276
                        }
277
                        literal.add(new DefaultAddressComponent(key, value));
278
                }
279

    
280
                NumberAddress address = new DefaultNumberAddress();
281
                address.setMainLiteral(literal);
282
                address.setNumber(number);
283
                return address;
284
        }
285

    
286
        /**
287
         * Saves the internal state of the object on the provided PersistentState
288
         * object.
289
         * 
290
         * @param state
291
         */
292
        public void saveToState(PersistentState state) throws PersistenceException {
293
                super.saveToState(state);
294
                state.set(FIRSTNUMBER, this.firstNumber);
295
                state.set(LASTNUMBER, this.lastNumber);
296
        }
297

    
298
        /**
299
         * Set the state of the object from the state passed as parameter.
300
         * 
301
         * @param state
302
         */
303
        public void setState(PersistentState state) throws PersistenceException {
304
                super.setState(state);
305
                this.firstNumber = (RelationsComponent) state.get(FIRSTNUMBER);
306
                this.lastNumber = (RelationsComponent) state.get(LASTNUMBER);
307
        }
308

    
309
}