Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libGeocoding / src / org / gvsig / geocoding / geommatches / MatcherUtils.java @ 27064

History | View | Annotate | Download (14.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.geommatches;
29

    
30
import java.awt.geom.PathIterator;
31
import java.util.ArrayList;
32
import java.util.HashMap;
33
import java.util.Iterator;
34
import java.util.List;
35

    
36
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.primitive.Curve2D;
39
import org.gvsig.fmap.geom.primitive.Point2D;
40
import org.gvsig.fmap.geom.util.Converter;
41
import org.gvsig.fmap.geom.util.UtilFunctions;
42
import org.gvsig.geocoding.result.DissolveResult;
43
import org.gvsig.geocoding.result.ScoredFeature;
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46

    
47
import com.vividsolutions.jts.geom.Coordinate;
48
import com.vividsolutions.jts.linearref.LengthIndexedLine;
49
import com.vividsolutions.jts.operation.overlay.OverlayOp;
50

    
51
/**
52
 * This class has the utilities to work with geometries and search th geocoding
53
 * point
54
 * 
55
 * @author <a href="mailto:jsanz@prodevelop.es"> Jorge Gaspar Sanz Salinas</a>
56
 * @author <a href="mailto:vsanjaime@prodevelop.es"> Vicente Sanjaime Calvet</a>
57
 */
58

    
59
public class MatcherUtils {
60

    
61
        private static final Logger log = LoggerFactory
62
                        .getLogger(MatcherUtils.class);
63

    
64
        /**
65
         * Get internal point from one geometry (polygon)
66
         * 
67
         * @param geomGV
68
         * @return
69
         */
70
        public static Point2D internalPointGeometry(Geometry geomGV) {
71

    
72
                com.vividsolutions.jts.geom.Geometry geomJTS = parseGeomGVToJTS(geomGV);
73
                if (geomJTS != null) {
74
                        com.vividsolutions.jts.geom.Point pto = geomJTS.getInteriorPoint();
75
                        return new Point2D(pto.getX(), pto.getY());
76
                }
77
                log.debug("Internal Point NULL ......");
78
                return null;
79
        }
80

    
81
        /**
82
         * parse geometries of gvSIG model to JTS model
83
         * 
84
         * @param geoms
85
         *            list of gvSIG geometries
86
         * @return list of JTS geometries
87
         */
88
        public static List<com.vividsolutions.jts.geom.Geometry> parseGeomsGVToJTS(
89
                        List<Geometry> geoms) {
90

    
91
                if (geoms != null && geoms.size() > 0) {
92
                        List<com.vividsolutions.jts.geom.Geometry> list = new ArrayList<com.vividsolutions.jts.geom.Geometry>();
93
                        com.vividsolutions.jts.geom.Geometry ge = null;
94
                        for (Geometry geometry : geoms) {
95
                                ge = Converter.geometryToJts(geometry);
96
                                list.add(ge);
97
                        }
98
                        return list;
99
                } else {
100
                        log.debug("List of geometries is NULL  ......");
101
                        return null;
102
                }
103
        }
104

    
105
        /**
106
         * Parse one gvSIG geomerty to JTS geometry
107
         * 
108
         * @param geom
109
         *            gvSIG geometry
110
         * @return JTS geometry
111
         */
112
        public static com.vividsolutions.jts.geom.Geometry parseGeomGVToJTS(
113
                        Geometry geom) {
114

    
115
                if (geom != null) {
116
                        com.vividsolutions.jts.geom.Geometry ge = Converter
117
                                        .geometryToJts(geom);
118
                        return ge;
119
                } else {
120
                        log.debug("Geometry is NULL  ......");
121
                        return null;
122
                }
123
        }
124

    
125
        /**
126
         * parse a list of gvSIG geometries to JTS geometries
127
         * 
128
         * @param geoms
129
         *            list gvSIG geometries to JTS geometries
130
         * @return
131
         */
132
        public static List<Geometry> parseGeomsJTSToGV(
133
                        List<com.vividsolutions.jts.geom.Geometry> geoms) {
134
                if (geoms != null && geoms.size() > 0) {
135
                        List<Geometry> list = new ArrayList<Geometry>();
136
                        Geometry ge = null;
137
                        for (com.vividsolutions.jts.geom.Geometry geometry : geoms) {
138
                                ge = Converter.jtsToGeometry(geometry);
139
                                list.add(ge);
140
                        }
141
                        return list;
142
                } else {
143
                        log.debug("List of geometries is NULL  ......");
144
                        return null;
145
                }
146
        }
147

    
148
        /**
149
         * Parse a gvSIG geometry to JTS geometry
150
         * 
151
         * @param geom
152
         *            gvSIg geometry
153
         * @return JTS geometry
154
         */
155
        public static Geometry parseGeomJTSToGV(
156
                        com.vividsolutions.jts.geom.Geometry geom) {
157
                if (geom != null) {
158
                        Geometry ge = Converter.jtsToGeometry(geom);
159
                        return ge;
160
                } else {
161
                        log.debug("Geometry is NULL  ......");
162
                        return null;
163
                }
164
        }
165

    
166
        /**
167
         * This method intersect two lines and return the intersection point. If
168
         * result is null, two lines doesn't intersect
169
         * 
170
         * @param geom1Jts
171
         * @param geom2Jts
172
         * @return
173
         */
174
        public static Point2D intersectTwoLinesJTS(
175
                        com.vividsolutions.jts.geom.Geometry geom1Jts,
176
                        com.vividsolutions.jts.geom.Geometry geom2Jts) {
177

    
178
                com.vividsolutions.jts.geom.Geometry interBBoxJTS = null;
179
                com.vividsolutions.jts.geom.Geometry geomPointJTS = null;
180

    
181
                if (geom1Jts != null && geom2Jts != null) {
182

    
183
                        interBBoxJTS = OverlayOp.overlayOp(geom1Jts.getEnvelope(), geom2Jts
184
                                        .getEnvelope(), OverlayOp.INTERSECTION);
185
                        if (interBBoxJTS.getGeometryType().compareTo("LineString") == 0
186
                                        || interBBoxJTS.getGeometryType().compareTo("Polygon") == 0) {
187
                                log.debug("Intersect: Intersect two BBOX");
188
                                geomPointJTS = OverlayOp.overlayOp(geom1Jts, geom2Jts,
189
                                                OverlayOp.INTERSECTION);
190

    
191
                                if (geomPointJTS.getGeometryType().compareTo("Point") == 0) {
192
                                        log.debug("Intersect: Intersect in the point X= "
193
                                                        + geomPointJTS.getCoordinate().x + " Y= "
194
                                                        + geomPointJTS.getCoordinate().y);
195
                                        Point2D pto = new Point2D(geomPointJTS.getCoordinate().x,
196
                                                        geomPointJTS.getCoordinate().y);
197
                                        return pto;
198
                                } else {
199
                                        log.debug("Intersect: Two lines don't intersect");
200
                                        return null;
201
                                }
202
                        } else {
203
                                log.debug("Intersect: Two BBOX don't intersect");
204
                                return null;
205
                        }
206
                }
207
                log.debug("Some Geometries are NULL  ......");
208
                return null;
209
        }
210

    
211
        /**
212
         * This method does the union the lines geometries (Features) with a
213
         * attribute common
214
         * 
215
         * @param scoreFeats
216
         * @return
217
         */
218
        public static List<DissolveResult> dissolveLinesJTS(
219
                        List<ScoredFeature> scoreFeats) {
220

    
221
                List<DissolveResult> result = new ArrayList<DissolveResult>();
222

    
223
                // Used array
224
                boolean[] used = new boolean[scoreFeats.size()];
225
                for (int i = 0; i < used.length; i++) {
226
                        used[i] = false;
227
                }
228

    
229
                // None elements
230
                if (scoreFeats.size() == 0) {
231
                        return null;
232
                }
233
                // Only one element
234
                else if (scoreFeats.size() == 1) {
235
                        DissolveResult res = new DissolveResult();
236
                        res.setGeom(scoreFeats.get(0).getDefaultGeometry());
237
                        List<ScoredFeature> list = new ArrayList<ScoredFeature>();
238
                        list.add(scoreFeats.get(0));
239
                        res.setScoredFeatures(list);
240
                        result.add(res);
241
                        return result;
242
                }
243
                // more elements
244
                else {
245
                        for (int i = 0; i < scoreFeats.size(); i++) {
246
                                ScoredFeature sfea1 = null;
247
                                ScoredFeature sfea2 = null;
248
                                com.vividsolutions.jts.geom.Geometry ge1 = null;
249
                                com.vividsolutions.jts.geom.Geometry ge2 = null;
250
                                List<ScoredFeature> feats = new ArrayList<ScoredFeature>();
251
                                DissolveResult res = new DissolveResult();
252
                                if (!used[i]) {
253
                                        sfea1 = scoreFeats.get(i);
254
                                        ge1 = MatcherUtils.parseGeomGVToJTS(sfea1
255
                                                        .getDefaultGeometry());
256
                                        used[i] = true;
257
                                        feats.add(sfea1);
258
                                        for (int j = 0; j < scoreFeats.size(); j++) {
259
                                                if (!used[j]) {
260
                                                        sfea2 = scoreFeats.get(j);
261
                                                        ge2 = MatcherUtils.parseGeomGVToJTS(sfea2
262
                                                                        .getDefaultGeometry());
263
                                                        if (ge1.touches(ge2)) {
264
                                                                used[j] = true;
265
                                                                ge1 = OverlayOp.overlayOp(ge1, ge2,
266
                                                                                OverlayOp.UNION);
267
                                                                feats.add(sfea2);
268
                                                        }
269
                                                }
270
                                        }
271
                                        res.setJTSGeom(ge1);
272
                                        res.setScoredFeatures(feats);
273
                                }
274
                        }
275
                }
276
                return result;
277
        }
278

    
279
        /**
280
         * This method does the union the polygon geometries with a attribute
281
         * common.
282
         * 
283
         * @param geomsJts
284
         * @return
285
         */
286
        public static List<DissolveResult> dissolvePolysJTS(
287
                        List<ScoredFeature> scoreFeats) {
288

    
289
                List<DissolveResult> result = new ArrayList<DissolveResult>();
290

    
291
                // Used array
292
                boolean[] used = new boolean[scoreFeats.size()];
293
                for (int i = 0; i < used.length; i++) {
294
                        used[i] = false;
295
                }
296
                // None elements
297
                if (scoreFeats.size() == 0) {
298
                        return null;
299
                }
300
                // One element
301
                else if (scoreFeats.size() == 1) {
302
                        DissolveResult res = new DissolveResult();
303
                        res.setGeom(scoreFeats.get(0).getDefaultGeometry());
304
                        List<ScoredFeature> list = new ArrayList<ScoredFeature>();
305
                        list.add(scoreFeats.get(0));
306
                        res.setScoredFeatures(list);
307
                        result.add(res);
308
                        return result;
309

    
310
                }
311
                // More elements
312
                else {
313
                        for (int i = 0; i < scoreFeats.size(); i++) {
314
                                ScoredFeature sfea1 = null;
315
                                ScoredFeature sfea2 = null;
316
                                com.vividsolutions.jts.geom.Geometry ge1 = null;
317
                                com.vividsolutions.jts.geom.Geometry ge2 = null;
318
                                com.vividsolutions.jts.geom.Geometry ge3 = null;
319
                                List<ScoredFeature> feats = new ArrayList<ScoredFeature>();
320
                                DissolveResult res = new DissolveResult();
321

    
322
                                if (!used[i]) {
323
                                        sfea1 = scoreFeats.get(i);
324
                                        ge1 = MatcherUtils.parseGeomGVToJTS(sfea1
325
                                                        .getDefaultGeometry());
326
                                        used[i] = true;
327
                                        feats.add(sfea1);
328

    
329
                                        for (int j = 0; j < scoreFeats.size(); j++) {
330

    
331
                                                if (!used[j]) {
332
                                                        sfea2 = scoreFeats.get(j);
333
                                                        ge2 = MatcherUtils.parseGeomGVToJTS(sfea2
334
                                                                        .getDefaultGeometry());
335
                                                        ge3 = ge1.intersection(ge2);
336
                                                        for (int k = 0; k < ge3.getNumGeometries(); k++) {
337
                                                                int dim = ge3.getGeometryN(k).getDimension();
338
                                                                if (dim == 1) {
339
                                                                        used[j] = true;
340
                                                                        ge1 = ge1.union(ge2);
341
                                                                        feats.add(sfea2);
342
                                                                        break;
343
                                                                }
344
                                                        }
345
                                                }
346
                                        }
347
                                        res.setJTSGeom(ge1);
348
                                        res.setScoredFeatures(feats);
349
                                }
350
                        }
351
                }
352
                return result;
353
        }
354

    
355
        /**
356
         * This method group geometries to one attribute
357
         * 
358
         * @param desc
359
         * @param features
360
         * @return
361
         */
362
        public static HashMap<String, List<ScoredFeature>> groupScoredFeaturesByAttribute(
363
                        FeatureAttributeDescriptor desc, List<ScoredFeature> features) {
364

    
365
                HashMap<String, List<ScoredFeature>> groups = new HashMap<String, List<ScoredFeature>>();
366
                Iterator<ScoredFeature> it = features.iterator();
367
                // Go for all geometries of the collection
368
                while (it.hasNext()) {
369
                        // Get feature
370
                        ScoredFeature feat = (ScoredFeature) it.next();
371
                        String key = feat.get(desc.getIndex()).toString();
372
                        // Store the geometries for attribute in the List
373
                        boolean contiene = groups.containsKey(key);
374
                        if (!contiene) {
375
                                List<ScoredFeature> featss = new ArrayList<ScoredFeature>();
376
                                featss.add(feat);
377
                                groups.put(key, featss);
378
                        } else {
379
                                ((List<ScoredFeature>) groups.get(key)).add(feat);
380
                        }
381
                }
382
                return groups;
383
        }
384

    
385
        /**
386
         * Calculate the position inside single line from distance
387
         * 
388
         * @param geomJTS
389
         * @param distance
390
         * @return
391
         */
392
        public static Point2D getLinePositionFromDistance(
393
                        com.vividsolutions.jts.geom.Geometry geomJTS, double distance) {
394

    
395
                LengthIndexedLine lenline = new LengthIndexedLine(geomJTS);
396

    
397
                if (lenline.isValidIndex(distance)) {
398
                        Coordinate coors = lenline.extractPoint(distance);
399
                        return new Point2D(coors.x, coors.y);
400
                }
401
                return null;
402
        }
403

    
404
        /**
405
         * Calculate the position inside single line from relative distance
406
         * 
407
         * @param geomJTS
408
         * @param distance
409
         * @return
410
         */
411
        public static Point2D getLinePositionFromRelativeDistance(
412
                        com.vividsolutions.jts.geom.Geometry geomJTS, int relative) {
413

    
414
                double totaldistance = geomJTS.getLength();
415
                LengthIndexedLine lenline = new LengthIndexedLine(geomJTS);
416

    
417
                Coordinate coors = null;
418

    
419
                if (relative < 0) {
420
                        coors = lenline.extractPoint(0);
421
                        return new Point2D(coors.x, coors.y);
422
                } else if (relative <= 100 && relative >= 0) {
423
                        double dist = (relative * totaldistance) / 100.0;
424
                        coors = lenline.extractPoint(dist);
425
                        return new Point2D(coors.x, coors.y);
426
                } else {
427
                        coors = lenline.extractPoint(totaldistance);
428
                        return new Point2D(coors.x, coors.y);
429
                }
430
        }
431

    
432
        /**
433
         * This method calculates a point perpendicular to the line at a distance
434
         * 
435
         * @param inicio
436
         * @param fin
437
         * @param linePoint
438
         * @param dist
439
         * @return
440
         */
441
        public static Point2D getPerpendicularPointFromLine(Point2D inicio,
442
                        Point2D fin, Point2D linePoint, double dist) {
443

    
444
                java.awt.geom.Point2D pto1 = new java.awt.geom.Point2D.Double(inicio
445
                                .getX(), inicio.getY());
446
                java.awt.geom.Point2D pto2 = new java.awt.geom.Point2D.Double(fin
447
                                .getX(), fin.getY());
448

    
449
                java.awt.geom.Point2D perpPoint = new java.awt.geom.Point2D.Double(
450
                                linePoint.getX(), linePoint.getY());
451

    
452
                java.awt.geom.Point2D[] p = UtilFunctions.getPerpendicular(pto1, pto2,
453
                                perpPoint);
454
                java.awt.geom.Point2D unit = UtilFunctions.getUnitVector(p[0], p[1]);
455

    
456
                java.awt.geom.Point2D res = new java.awt.geom.Point2D.Double(perpPoint
457
                                .getX()
458
                                + (unit.getX() * dist), perpPoint.getY() + (unit.getY() * dist));
459

    
460
                return new Point2D(res.getX(), res.getY());
461
        }
462

    
463
        /**
464
         * Calculate the position in the line with offset
465
         * @param geoms
466
         * @param linePoint
467
         * @param dist
468
         * @return
469
         */
470
        public static Point2D getOffsetPosition(Geometry[] geoms,
471
                        Point2D linePoint, double dist) {
472

    
473
                for (int j = 0; j < geoms.length; j++) {
474
                        double[] coords = new double[6];
475
                        Point2D inicio = null;
476
                        Point2D fin = null;
477

    
478
                        boolean inter = geoms[j].intersects(linePoint.getBounds2D());
479
                        if (inter) {
480
                                PathIterator iter = ((Curve2D) geoms[j]).getGeneralPathX()
481
                                                .getPathIterator(null);
482
                                iter.currentSegment(coords);
483
                                inicio = new Point2D(coords[0], coords[1]);
484

    
485
                                iter.next();
486
                                iter.currentSegment(coords);
487
                                fin = new Point2D(coords[0], coords[1]);
488

    
489
                                log.debug("Return point with offset");
490
                                return MatcherUtils.getPerpendicularPointFromLine(inicio, fin,
491
                                                linePoint, dist);
492
                        }
493
                }
494
                log.debug("Return original point without offset");
495
                return linePoint;
496

    
497
        }
498

    
499
}